|
|||||||
|
|
Thread Tools | Display Modes |
#1
|
|||||
|
|||||
|
XNA Tutorials - First Update -
02-19-2007
, 01:48 PM
Hog Racing - Update 1
Source Not quite what you expected? Despite this looking nothing like it may finally do, many of the concepts are already there. I'm going to presume you have XNA installed (if you don't, look at the tutorial below) and have opened up the source files. If you've tried to create a game before, you will realise that some of the code is pregenerated - most of this remains unchanged, but has been added to. First, some concepts: X and Z are 'horizontal', Y is up/down A wheel needs to know where it is in relation to it's car. A wheel does not need to know where other wheels are. A wheel does not need to know what a car looks like. A car has 4 wheels. A car does not need to know what the wheels look like A car should know it's speed and location. A car should be able to look after itself A car shouldn't need to know about other cars (until we do collisions) The world needs to have cars in. The world does not care where these cars are, or how fast they are moving The world does not need to know where the cars wheels are. Everything -should- use the same physics. To this end, classes have been created. The best way to describe classes it to look at real life. A 'human' would be a class, as we all have the same basic features. The traits, however, are different. A car is similar to this - they all need the same things, but the exact values of these things does not matter. They need a speed and a position, but that can be anything. Because of this, a Car class has been created. This can be found in Car.cs. Code:
#region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; #endregion Code:
namespace Hog_Racing
{
class Car
{
//information about the car
Model model;
Vector3 position;
Vector3 speed;
Vector3 rotation;
Int16 player;
//the physics system we will use, doing this would allow us to have cars with different physics.
Physics physics;
//Where the wheels will eventually be stored.
Wheel[] wheels = new Wheel[4];
int mass;
It also says that the Car class has members of things like speed (Should be velocity), position, rotation etc. This is what it know about itself. The word before the name is the type of information it knows about itself. A Vector3 is essentially three numbers held together in one piece of information, and these are assigned the names X,Y and Z and can quite handily match up to the three dimensions we usually use. :) int stands for a 32 bit integer, which is a whole number. float can be used if we want decimals. Int16 is a 16 bit integer, which I have used as I doubt we will ever have that many players! (16 bit is still 65536 possible values). Then it gets a bit odd. Wheel[] wheels = new Wheel[4] does two things. It tells the code that there exists a member called wheels of class Wheel, but because it's an array (a grouping, denoted by []), we also say that it is an array of 4 things of a Wheel class. This can also be done, and will be seen elsewhere with integers. E.g int temporaryinteger = 0; where the integer is created and set to 0 immediately. Physics physics; is a little confusing, but it just means that there is a member called physics which is of the class Physics. More on this later. Code:
public Car(Vector3 position1, Vector3 rotation1, Int16 player1, Physics physics1, int mass1)
{
//'save' the starting settings for the car
position = position1;
rotation = rotation1;
physics = physics1;
player = player1;
mass = mass1;
}
Code:
public void update(GamePadState input)
{
//update everything to do with the 'car' - calculate it's new speed, use the speed to modify the position and then use the speed to work out the rotation of the ball
speed += physics.findacceleration(new Vector3(input.ThumbSticks.Right.X, 0, input.ThumbSticks.Right.Y), mass);
position += speed;
rotation += (speed / (MathHelper.TwoPi)) * MathHelper.TwoPi;
}
It is a public void, which means it can be called from code not in the class Car but does not return anything. 'speed += ...' is shorthand for saying 'speed = speed +' - we are not overwriting the value, we are modifying it. physics is a variable holding a class Physics - the same one that got passed to the Constructor. '.findacceleration' is a function call to a function of the physics class called 'findacceleration' (Physics.cs). This is a public, but it is not a void. It is a public Vector3, which means it returns a Vector3. Because of this, it can be used instead of a Vector3 variable in an equation, as it is here. We are adding it to our Vector3 of speed, which just means it adds the X, Y and Z components individually. It takes two 'arguments' (things we pass to it), a Vector 3 of 'forces' and the mass of the object. Because we want to use the position of the thumbsticks to act as the value of forces, we have to use 'new Vector3(...)' to 'mash' them into a Vector3. Note how we put them into the X and Z sections of the Vector3 - we don't want flying cars!. The code then adds the speed to the position, thereby moving the object. The next line is just for fun, and can be worked out if you want to (ball radius 1). This just makes the ball appear to spin. Code:
public Vector3 getposition()
{
//tell me where the car is!
return position;
}
Code:
class Physics
{
public Physics()
{
}
public Vector3 findacceleration(Vector3 force, int mass)
{
//Using F=ma
Vector3 temp = Vector3.Zero;
// a = F/m (*Cringe*, don't make me do that again)
temp = force / mass;
//send back the acceleration in the 3 directions
return temp;
}
This is the fabled findacceleration function - we pass it a force and a mass and it uses Newton's second law to calculate the acceleration, which it returns. From Game.cs Code:
//An array holding all the cars, so far only 1.
Car[] Cars = new Car[1];
Model terrain;
Physics physics;
protected override void Initialize()
{
//set the global physics to be a Physics class (see Physics.cs)
physics = new Physics();
// TODO: Add your initialization logic here
//Create a new car, Starting position 1,1,1 (The ball's radius is 1), no rotation, playernumber 1 and the same physics as the global, mass 100
// The array of cars has one item in it, address '0'
Cars[0] = new Car(Vector3.One, Vector3.Zero, 1, physics, 100);
base.Initialize();
}
Cars[0] = new Car(Vector3.One, Vector3.Zero, 1, physics, 100); Creates one car by calling the constructor. If you scoll back up, you will see that this means that the position is 1,1,1 (Vector3.One is a default thing 1,1,1), with no rotation, player number 1, a physics class (so we can make sure all cars use the same one) and a mass of 100. Code:
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
//terrain = content.Load<Model>("Models//480polygonsnookerball");
terrain = content.Load<Model>("Terrain//flatground");
Model temp = content.Load<Model>("Models//480polygonsnookerball");
//set the car model to this
Cars[0].setmodel(temp);
}
// TODO: Load any ResourceManagementMode.Manual content
}
So far, all these functions have been run once when the game loads (XNA handles calling them). These next two functions are called by XNA every cycle (60 times/second) Code:
protected override void Update(GameTime gameTime)
{
// Allows the default game to exit on Xbox 360 and Windows
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
//Update all the cars, see tutorial 1
for (int i = 0; i < Cars.GetLength(0); i++)
{
Cars[i].update(GamePad.GetState(PlayerIndex.One));
}
//The camera is pointing at the first 'car', see the function getposition in the Car class
cameraTarget = Cars[0].getposition();
//Use the left stick and buttons to adjust where the camera is.
cameraPosition.X += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X;
cameraPosition.Z += GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.Y;
if (GamePad.GetState(PlayerIndex.One).Buttons.LeftShoulder == ButtonState.Pressed)
cameraPosition.Y -= 1;
if (GamePad.GetState(PlayerIndex.One).Buttons.RightShoulder == ButtonState.Pressed)
cameraPosition.Y += 1;
// TODO: Add your update logic here
base.Update(gameTime);
}
Gamepad.GetState(Playerindex.One) returns the current state of the Gamepad as a Gamepadstate, so we can assign it to a Gamepadstate variable and pass it to our car for that to look at. If you look, the car never knows which gamepad it's looking at, it just know the current state of the one the world tells it about. for (int i = 0; i < Cars.GetLength(0); i++) { ... } is a loop. There are three things that we tell it - it's looping using a variable called 'i' which begins at 0, it can continue while i is less than Cars.GetLength(0) (How big the Car array is, in this case '1') and each time it runs it should add 1 to i (i++) Because i has to be less than 1, this loop currently only runs once, while i equals 0. In this time, it updates the Car in the array position i, or Car[0] by calling it's update function which we've already looked at. If there were two cars, it would run twice without me having to edit this code :) The next bit uses the state of controller 1 to move the camera - there are 'if' statements there, but they have their own section below. Finally Code:
protected override void Draw(GameTime gameTime)
{
//Clear screen
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
//Prewritten code from helpfiles ---VVVVV
Matrix[] transforms = new Matrix[terrain.Bones.Count];
terrain.CopyAbsoluteBoneTransformsTo(transforms);
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in terrain.Meshes)
{
//This is where the mesh orientation is set, as well as our camera and projection
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.DiffuseColor = Color.Green.ToVector3() ;
effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationX(MathHelper.ToRadians(180))
* Matrix.CreateTranslation(Vector3.Zero);
effect.View = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),
aspectRatio, 1.0f, 10000.0f);
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
//Prewritten ----- ^^^^^
//Draw all the cars, see updating for more information.
for (int i = 0; i < Cars.GetLength(0); i++)
{
//calls the draw function of each car in turn, see Car.cs
Cars[i].draw(cameraPosition, cameraTarget, aspectRatio);
}
base.Draw(gameTime);
}
effect.DiffuseColor = Color.Green.ToVector3() ; means that the untextured surface reflects green light, making it look green. Color.Green is a predefined colour like Vector3.One, but this property does not like colours and instead insists on Vector3s where XYZ = RGB. No matter, the Color class can convert to it with the function 'toVector3()' Once again a loop calls the draw function of the cars, where each will eventually do the same to their wheels. This way, the world does not need to know anything about the wheels of the car :). Code:
effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationZ(-rotation.X) * Matrix.CreateRotationY(rotation.Y) * Matrix.CreateRotationX(rotation.Z) * Matrix.CreateTranslation(position); If statements: If statements are possibly the most useful thing and are required for a computer to be Turing Complete. In C#, they have the following basic outline: if (<something>) { <do this> } else { <do this if not something> } If you only need one line of <do this>, then the {} can be ommited as seen in the camera movement code. <something> can be more than one thing, linked with operators. (variable == 6) will <do this> is the variable equals 6 (DON'T USE '='!!!) != means does not equal (var1 == 5 && var2 == 3) means that var1 must equal 5 AND var2 must equal 3. (var1 == 4 || var2 == 3) means 'or' - there are a few more, but they can be looked up. Booleans are a variable type, like integer or Vector3 that can only either be True or False. Because of this, in if statements a shorthand can be used. if (boolean) will <do this> if the boolean is set to true - there is no need to say ==true. This thread took a fair while to write, so there may be errors. Post any questions you have in this thread, or any suggestions/ideas/works of your own/ammendments. If you are unsure about anything ask so it can be clarified. All the source code is available (link at top) and we expect an update from the 3D modeller soon regarding the track! There may be another upate in a few hours, there may not be. http://www.bathgatehall.co.uk/webcam1.php may occaisionally have a live video feed of something - I'll post if it does. Controls - RB/LB = Camera Up/Down Left Stick = Camera Move Right Stick = Apply force to ball Below is a previous tutorial by Mikleran written while I was writing some code for walls >_>. Quote:
|
#2
|
|||||
|
|||||
|
02-19-2007
, 02:47 PM
Well, it looks like i'm going to be the MEE in this project. The Mister Everything Else does all the bits that noone else is willing to do, basically!
The first job I've got is to make the map: it's pretty much needed once the basic physics has been done (like Daleks has done in the first post), and since our modeller couldn't be arsed to do it today, it was left to me. Well, as a big F1 fan, i've decided to make the map an F1 track. We decided that the track had to be flat, as it would be impossible to figure out and implement the physics in 5 days, and would be a nightmare for a tutorial! The track that I decided to do is called 'Albert Park'; It's been the host of the Australian Formula One Grand Prix since 1996. It's quite a nice track, with a couple of longish straights in it, but also a nice number of corners with varying degrees of steepness. To create the model, I started out by scanning in a card containing a plan of AlberT Park in through ABBYYFine. About 600DPI was adequate, since that's roughly what the printer used. It's got slightly skewed proportions, with the track being about 3 times wider than it should be; which is excellent! It means that the track is only going to be about half a mile long, rather than 3 and a half! For creating this model, I used Google Sketchup; a free download from http://sketchup.google.com. I imported the texture, made a box about the right size for it and textured it! The end result was something like this: ![]() In that picture, i've outlined the track using the pen tools. This means that i can delete the texture inside the track and replace it with a much higher resolution asphalt one in the future. In fact, i pretty much outlined everything in the map, from the graveltraps to the tyrewalls to the grandstands. I then removed their textures, and replaced them with generic ones for now (simple colours). I've also made the Grandstand's 3D, and made the lake blue with the islands raised up inside it. This was a fairly easy job; it just takes time. If you've got any questions, don't hesitate to ask! The result as of 5 mins ago: ![]() It's all very basic for now, and looks awful. But it will improve! ;) |
#3
|
|||||
|
|||||
|
02-20-2007
, 07:41 PM
Hog Racing - Update 2 Source![]() First, I'd like to thank everyone for their support and overwhelming interest in this thread ![]() Anyway, as you can see from this 5 hour old screen shot, we now have a track to race around! (The car is bigger now) http://daleks.bathgatehall.co.k/XNA/Melbourne.JPG is a top down map that we use later for some easy collision detection, but should give you a good idea of what is going on. Most of the changes have been fairly superficial like that, althoguh the update tomorrow should be good. A few major changes have occured - effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 100000000.0f); The large number in there is now even larger - that is the draw distance, and is so you can see the entire map at the same time. In Car.cs, the code car movement code has been changed to have the left and right triggers as acceleration, using the direction of the car as the forward point. The maths is fairly intermediate, if someone wants me to go through it I'll do it in the update tomorrow. The camera code has also been altered slightly to make it easier, and the car now starts in the middle of the track. The new map requires textures, which were not required before. The textures are put in a subfolder, but that is to do with the porgram used to export them. If you open the .fbx file you will see the path names to the textures - these can be altered if so required. The main jobs last night was the modelling of the map and the 2D version - now that is complete, we can move on to collisions with the environment. (After wheels of course!) Forum Problems? Spam? Need help? Think I've been a harsh, evil, unfair git? PM me |
#4
|
|||||
|
|||||
|
02-20-2007
, 08:30 PM
Well, I did almost nothing new yesterday, apart from learning what a complete pile of poopoo Google SketchUp is for Exporting models to FBX format.
I've had to redo the entire model; first attempt took 5 hours and in the new model i've done about 3. The latest model is slightly better,: this is a picture of the first corner: ![]() Dalek doesn't have that model in game yet so the screens above are missing some of the detail. The grandstands will look better in the final model! :) The corner is famous for Ralf Schumacher's crash there in 2002(?). It was a pretty huge shunt.. ![]() And c'mon, people said they wanted this thread; yet no responses! |
#5
|
|||||
|
|||||
|
02-21-2007
, 07:56 PM
Hog Racing - Update 3 SourceWe get closer to looking like a game today, with the addition of cubes to aid movement. Lots of behind the scenes posturing to work out how to sort of do the next bit too. One major thing that may encourage someone to ask a question is the inclusion of keyboard control - so you don't need a 360 controller to play (although you don't have -full- control). This code can be found in Game.cs and Car.cs. Code:
if (Keyboard.GetState().IsKeyDown(Keys.A)) cameraPosition.Y -= 10; Wheels have also been added since the last update. The same way that the game calls update on the cars, so the cars update and draw their own wheels. The are created with the car, and get told their relative position. This is converted into a distance and an angle from the centre of the car. Each time the wheel is drawn, it takes that into account using trig to keep the wheel in the correct place. The wheels do spin, but the wrong way sometime. Working on it. Any suggested fixes could be sent in a PM :) The back wheels also need to reverse in spin direction, ala Hog. See program :P Tomorrow should be audio and the use of wheels to turn - anyone who has downloaded it (I know ONE person has) will have noticed the not very much friction like environment - that should be fixed tomorrow: I will look at the direction of the driving wheels, and apply forces to the car based on this and the speed. I can cancel out any movement by applying a force equal to the negative speed multiplied by the mass, as the mass is cancelled out in the equation leaving an instant decceleration. If I use a percentage of the mass, I can control the skid of the car. Forum Problems? Spam? Need help? Think I've been a harsh, evil, unfair git? PM me |
#6
|
|||||
|
|||||
|
02-21-2007
, 07:56 PM
Latest Build:
![]() When the hog model is added it should look acceptable! ;) |
#7
|
|||||
|
|||||
|
02-21-2007
, 09:12 PM
![]() |
#8
|
|||||
|
|||||
|
02-23-2007
, 06:54 AM
*bump*
Both of our copies of Crackdown came yesterday so nothing got done! :lol: Since there seems to be very little interest in this thread there doesn't seem to be much point in finishing it any time soon either. We'll see what time we get; but some interest would be nice! |
#9
|
|||||
|
|||||
|
02-23-2007
, 05:30 PM
Wwwwwwwwwwwwwwwwwwwwwaaaaaaaaaaaaaa aaaaaaawh. This looks like ALOT of work, wish I could afford the XNA subscription
|
#10
|
|||||
|
|||||
|
02-23-2007
, 08:46 PM
Everything we did here is FREE - the subscription lets you play it on the 360, whereas this game is coded (at the moment) for PC.
Forum Problems? Spam? Need help? Think I've been a harsh, evil, unfair git? PM me |
#11
|
|||||
|
|
|||||
|
02-24-2007
, 03:07 PM
Amazing, wish i could help but I don't know much about this stuff.
|
#12
|
|||||
|
|||||
|
02-24-2007
, 05:36 PM
Quote:
BTW: ![]() In Game ;) *ahem* |
#13
|
|||||
|
|||||
|
03-04-2007
, 02:18 PM
Whoa, seriously? You have to be pulling my leg.
|
#14
|
|||||
|
|||||
|
03-05-2007
, 08:33 PM
I think he was making a joke about some of the 'in game videos' that have been released. Too bad it sucked :P [I haven't see that level of detail anyway :P]
Forum Problems? Spam? Need help? Think I've been a harsh, evil, unfair git? PM me |
#15
|
|||||
|
|||||
|
03-06-2007
, 12:07 AM
I'm inexperienced on this stuff but it is very interesting. I would like for this to be completed. Not right away obviously, but in the future.
|
#16
|
|||||
|
|||||
|
03-07-2007
, 08:23 PM
Yeah, I think it will be. Unfortunatley, magical Friday hit so life came back again :(
Friday we have a 3 hour programming competition (www.olympiad.org.uk) and a 1 hour Physics one, www.dreambuildplay.com has a slightly greater incentive to do things quickly and I was up till 2AM doing Calculus last night :) Forum Problems? Spam? Need help? Think I've been a harsh, evil, unfair git? PM me |
#17
|
|||||
|
|||||
|
03-10-2007
, 04:24 PM
Quote:
We have what we think would be a cool idea for a game and so we are going to try and make it for the DreamBuildPlay competition. I doubt anything will be posted in here anytime soon, but it will be a cool game if we finish it. @Whole Ingame screenshot thing.. LOL! That's just a Google Earth pic of the section i showed in a true ingamescreen earlier. I made the track about 3-4x wider than it actually is in reality and then shrunk it down so that a lap of the track wouldn't take about 20mins! We will finish the project sometime.. although don't be surprised if it isn't after July 2nd! |
#18
|
|||||
|
|||||
|
03-16-2007
, 11:45 PM
I want to try this, but all I have done with gamemaking is just gamemaker. I did some slight coding in that, but that's it. I hope there are good tuts? Because this looks interesting.
EDIT: Does XNL work with Visual Basic? Because I got that one because it sounded simple. -Aqua
Last edited by AquaEchoiii; 03-17-2007 at 11:30 PM.
.
|
#19
|
|||
|
|||
|
03-30-2007
, 02:45 PM
Wow. O_O That looks fantastic
I would love to do something like that myself, I just have no idea where to even begin. |
#20
|
|||||
|
|||||
|
03-30-2007
, 07:03 PM
Have a go at reading the tutorial! If it's too complicated/far too difficult looking just say and it'll help if we can be arsed to do a revision of it. :lol:
|
| Thread Tools | |
| Display Modes | |
|
|