Post on 14-Dec-2015
transcript
Constructor and New Fields // Don't synch draw() with vertical retrace of monitor
graphics.SynchronizeWithVerticalRetrace = false;
IsFixedTimeStep = true; // default rate of 1/60 sec
private float fps;
private float updateInterval = 1.0f;
private float timeSinceLastUpdate = 0.0f;
private float framecount = 0;
IsFixedTimeStep, when true, will cause XNA to call Update() only after TargetElapsedTime seconds
have passes.
In Constructor
New private member fields.
New XNA 3.0 Windows GameIn Visual Studio 2008
File -> New -> Project Project Type: XNA Game Studio 3.0 -> Windows
Game (3.0) Name: Pong (or whatever you’d like)
Let’s create some spritesIn solution explorer
Under content <right click> -> Add new item->Bitmap file Create a Ball (mine is 12x12)
Might want to rename it to ball Create a Paddle -- maybe name it paddle (mine is
14x56)
Before we go to far what objects?Ball
Position 2d vector
Velocity 2d vector
PaddlePosition
2d vectorVelocity ?
Maybe, depends on if it keeps moving when user stops pressing button. For now yes
What about dimensions?
Let’s create helper class(es)namespace Pong1{ public class Thingy { public int Height { get; set; } public int Width { get; set; } public Vector2 position { get; set; } public Vector2 motion { get; set; } public Rectangle rect { get { return new Rectangle((int)position.X, (int)position.Y, (int)Width, (int)Height); } } } public class Paddle : Thingy { } public class Ball : Thingy { }
What is this?
Declare some variablesBall theBall;Paddle paddle1;Paddle paddle2; Texture2D ballTexture;Texture2D paddleTexture;const int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;
Initialize() // Setup window dimensions. // We could also used defaults and querygraphics.PreferredBackBufferHeight = SCREEN_HEIGHT;graphics.PreferredBackBufferWidth = SCREEN_WIDTH;graphics.PreferMultiSampling = false;graphics.ApplyChanges(); // Initialize Ball theBall = new Ball();theBall.position = new Vector2(30, 30); theBall.motion = new Vector2(3f, 1f);theBall.Width = 12;theBall.Height = 12;
Initialize() // Initialize Paddlespaddle1 = new Paddle();paddle1.position = new Vector2(0, 10);paddle1.motion = new Vector2(0, 3);paddle1.Width = 14;paddle1.Height = 56;
paddle2 = new Paddle();paddle2.position = new Vector2(630, 30);paddle2.motion = new Vector2(0, -3);paddle2.Width = 14;paddle2.Height = 56;
Load and Display SpritesLoadContent()ballTexture = Content.Load<Texture2D>("ball");paddleTexture = Content.Load<Texture2D>("Paddle");
Draw()spriteBatch.Begin();spriteBatch.Draw(ballTexture, theBall.position, Color.White);spriteBatch.Draw(paddleTexture, paddle1.position, Color.Blue);spriteBatch.Draw(paddleTexture, paddle2.rect, Color.Red);spriteBatch.End();
<F5>
Vector2
Rectangle
Let’s move the ball and paddlesUpdate()// Move ball and make it bounce at boundaries.
theBall.position += theBall.motion;if (theBall.position.X <= 0 || theBall.position.X >= SCREEN_WIDTH) theBall.motion = new Vector2(theBall.motion.X, theBall.motion.Y); // reverse X direction
if (theBall.position.Y <= 0 || theBall.position.Y >= SCREEN_HEIGHT - theBall.Height)theBall.motion = new Vector2(theBall.motion.X, -theBall.motion.Y);
Let’s move the ball and paddlesUpdate()paddle1.position += paddle1.motion;if (paddle1.position.Y <= 0) { // Don’t let it go beyond screen.
paddle1.position = new Vector2(paddle1.position.X, 0); paddle1.motion = new Vector2(paddle1.motion.X, -paddle1.motion.Y)
}if (paddle1.position.Y >= SCREEN_HEIGHT-paddle1.Height)
paddle1.position = new Vector2(0, SCREEN_HEIGHT - paddle1.Height);
paddle2.position += paddle2.motion;if (paddle2.position.Y <= 0) {
paddle2.position = new Vector2(paddle2.position.X, 0);paddle2.motion = new Vector2(paddle2.motion.X, -paddle2.motion.Y);
}if (paddle2.position.Y >= SCREEN_HEIGHT - paddle2.Height) {
paddle2.position = new Vector2(paddle2.position.X, SCREEN_HEIGHT - paddle2.Height);
paddle2.motion = new Vector2(paddle2.motion.X, -paddle2.motion.Y); }
This code looks very similar. Begs for a
convenience function
<F5> Compile and run
Lets add soundSolution Explorer
Content <right click> Add -> New folder
Name it sound or audio Right click on your new folder
Add -> existing item Browse for a sound file you’d like to use, search
for .wav I used ding.wav
Also find sounds from the web Can use audacity to make and record them
Without using XACTDeclare variable.SoundEffect hitWallSound;
LoadContent()ContentManager contentManager = new
ContentManager(this.Services, @"Content\sound\");hitWallSound = contentManager.Load<SoundEffect>("ding");
Everytime ball hits a wall (in your update)
if (theBall.position.Y <= 0 || … ){hitWallSound.Play();theBall.motion = new Vector2(X, -Y);
} <F5> Compile and run
Collide ball with paddle(s)In update()if (CollisionWithPaddle()) {hitPaddleSound.play();theBall.motion = new Vector2(
theBall.motion.X*1.03f, theBall.motion.Y*1.03f);}
Speed up by 3% each hit
CollisionWithPaddle()private bool CollisionWithPaddle() { if (theBall.motion.X > 0) {//Moving Left must hit player2 return(RectsCollide(paddle2.position.X, paddle2.position.Y, paddle2.Width, paddle2.Height, theBall.position.X,
theBall.position.Y,theBall.Width, theBall.Height)); else return(RectsCollide(paddle1.position.X, paddle1.position.Y, paddle1.Width, paddle1.Height, theBall.position.X, theBall.position.Y, theBall.Width, theBall.Height));
}
RectsCollide() private bool RectsCollide(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) { if (x2 - w2<= x1 && x1 <= x2 + w2 && y1 - h2 <= y2 && y2 <= y1 + h1) return true; else return false; }
This is one way to see if two rectangles overlap. For many collisions you’ll want
to do pixel level collisions. Many examples on the web, start with
overlapping rectangles, then check for two pixels in the overlap that are not
transparent.
One player game - update()GamePadState pad1 = GamePad.GetState(PlayerIndex.One);paddle1.motion = new Vector2(0, 0);if (pad1.DPad.Down == ButtonState.Pressed) paddle1.motion = new Vector2(0, 5);if (pad1.DPad.Up == ButtonState.Pressed) paddle1.motion = new Vector2(0,-5);if (pad1.ThumbSticks.Left.Y != 0) paddle1.motion = new Vector2(0,pad1.ThumbSticks.Left.Y*-5.0f);paddle1.position += paddle1.motion;if (paddle1.position.Y <= 0) paddle1.position = new Vector2(paddle1.position.X, 0);if (paddle1.position.Y >= SCREEN_HEIGHT-paddle1.Height) paddle1.position=new Vector2(0,SCREEN_HEIGHT- paddle1.Height);
arrow pad or the left thumb stick will move paddle. Could add keyboard arrow keys.KeyboardState keyboard = Keyboard.GetState(); keyboard.IsKeyDown(Keys.Up)
Don’t allow paddle to go past borders
<F5> Compile and run Can add AI for other player or paddle2.Height = 356;
ScoreSolution Explorer
Content (right click) Add -> New Item
Sprite Font Change name to Courier New.spritefont
This name is what you want to call it in the program
Now in the editor, edit the XML to your desireChange the fontname to Courier New or whatever
you want, you can look in control panel for available fonts.
Change the size to 32 for this exampleCan change anything else you want
ScoreCreate a type and declare some variablespublic class Aplayer { private int _score = 0; public int Score { get { return _score; } set { _score = value; } } }APlayer player1;APlayer player2;
In initialize() player1 = new APlayer();player2 = new APlayer();
Score - Update()if (theBall.position.X <= 0 || theBall.position.X >= SCREEN_WIDTH) // Someone has scored!
{ PlayWallHit(); if (theBall.motion.X < 0) player2.Score++; else player1.Score++; float L = theBall.motion.Length(); theBall.motion *= new Vector2(-3.0f/L, 3.0f/L); theBall.position = new Vector2(320, theBall.position.Y); // Start ball in the middle
}
Can’t just call normalize() since position is a struct and not a class.
ScoreDeclare some variables
SpriteFont Font1;Font1 = Content.Load<SpriteFont>("Courier New");Vector2 score1Pos;score1Pos = new Vector2(30,30) // Initialize
Draw scorespriteBatch.DrawString(Font1, player1.Score.ToString(), score1Pos, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
If you want to center about point Vector2 FontOrigin = Font1.MeasureString(score) / 2;spriteBatch.DrawString(Font1, score, score1Pos, Color.White, 0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f);