Programowanie telefonów z Windows Phone 7, cz. 3 Piotr M. Szczypiński Instytut Elektroniki Politechniki Łódzkiej http://www.eletel.p.lodz.pl/pms/ piotr.szczypinski@p.lodz.pl Budynek B9, II piętro, pokój 217A 1/34
Dziś w menu 1. XNA i grafika raczej płaska wypisywanie tekstu w XNA SpriteFont wyświetlanie map bitowych Texture2D obsługa ekranu dotykowego TouchCollection wykrywanie kolizji BoundingBox efekty dźwiękowe SoundEffect 2. XNA i trójwymiarowość definiowanie obiektów trójwymiarowych transformacje współrzędnych obiektów ustawienie kamery i rzutowanie obrazu na płaszczyznę ekranu bryła obcinania, ukrywanie ścianek 2/34
XNA i grafika raczej płaska Zróbmy prostą grę z dwoma obiektami (ang. sprite). Jeden z obiektów będzie się poruszał i odbijał od brzegów ekranu. Położenie drugiego obiektu będziemy kontrolować dotykając ekran. Obiekty będą się zderzać, kolizję trzeba wykryć i wygenerować efekt dźwiękowy. 3/34
XNA i grafika raczej płaska Przed utworzeniem nowego projektu trzeba przygotować mapy bitowe spritów (z przeźroczystością) i dźwięk efektu zderzenia. brzdek.wav sprite1.png sprite2.png 4/34
5/34
1 (add existing item) 2 3 6/34
1 (add new item) 2 7/34
2 1 8/34
9/34
Wypisywanie tekstu public class Game1 : Microsoft.Xna.Framework.Game GraphicsDeviceManager graphics; SpriteBatch spritebatch; string text = "Witaj XNA"; SpriteFont font1; Vector2 textposition1; public Game1() graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content";... // Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); Update() Draw() 10/34
Wypisywanie tekstu protected override void LoadContent() // Create a new SpriteBatch, which can be used to draw textures. spritebatch = new SpriteBatch(GraphicsDevice); font1 = this.content.load<spritefont>("spritefont1"); Vector2 textsize = font1.measurestring(text); Viewport viewport = this.graphicsdevice.viewport; textposition1 = new Vector2((viewport.Width - textsize.x) / 2, (viewport.height - textsize.y) / 2); 11/34
Wypisywanie tekstu protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.SaddleBrown); spritebatch.begin(); spritebatch.drawstring(font1, text, textposition1, Color.Black); spritebatch.end(); base.draw(gametime); 12/34
Wyświetlanie map bitowych public class Game1 : Microsoft.Xna.Framework.Game GraphicsDeviceManager graphics; SpriteBatch spritebatch; string text = "Witaj XNA"; SpriteFont font1; Vector2 textposition1; Texture2D texture1; Texture2D texture2; Vector2 spriteposition1; Vector2 spriteposition2; Vector2 spritespeed1 = new Vector2(100.0f, 50.0f); SoundEffect soundeffect;... 13/34
Wyświetlanie map bitowych protected override void LoadContent()... texture1 = Content.Load<Texture2D>("sprite1"); texture2 = Content.Load<Texture2D>("sprite2"); soundeffect = Content.Load<SoundEffect>("brzdek"); spriteposition1.x = 0; spriteposition1.y = 0; spriteposition2.x = graphics.graphicsdevice.viewport.width - texture2.width; spriteposition2.y = graphics.graphicsdevice.viewport.height - texture2.height; 14/34
Wyświetlanie map bitowych protected override void Update(GameTime gametime) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.exit(); UpdateSprite(gameTime, ref spriteposition1, ref spritespeed1); base.update(gametime); protected override void Draw(GameTime gametime)... spritebatch.begin(spritesortmode.backtofront, BlendState.AlphaBlend); spritebatch.draw(texture1, spriteposition1, Color.White); spritebatch.end(); base.draw(gametime); 15/34
UpdateSprite(GameTime gametime, ref Vector2 spriteposition, ref Vector2 spritespeed) void spriteposition += spritespeed * (float)gametime.elapsedgametime.totalseconds; int int int int Right = graphics.graphicsdevice.viewport.width - texture1.width; Left = 0; Bottom = graphics.graphicsdevice.viewport.height - texture1.height; Top = 0; if (spriteposition.x > Right) spritespeed.x *= -1; spriteposition.x else if (spriteposition.x < Left) spritespeed.x *= -1; spriteposition.x if (spriteposition.y > Bottom) spritespeed.y *= -1; spriteposition.y else if (spriteposition.y < Top) spritespeed.y *= -1; spriteposition.y = Right; = Left; = Bottom; = Top; 16/34
Obsługa ekranu dotykowego protected override void Update(GameTime gametime) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.exit(); TouchCollection touchlocations = TouchPanel.GetState(); if (touchlocations.count > 0) foreach (TouchLocation touchlocation in touchlocations) if (touchlocation.state == TouchLocationState.Pressed touchlocation.state == TouchLocationState.Moved) spriteposition2.x = touchlocation.position.x - texture2.width / 2; spriteposition2.y = touchlocation.position.y - texture2.height / 2; //spriteposition2 = touchlocation.position;... 17/34
Obsługa ekranu dotykowego protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.SaddleBrown); spritebatch.begin(); spritebatch.drawstring(font1, text, textposition1, Color.Black); spritebatch.end(); spritebatch.begin(spritesortmode.backtofront, BlendState.AlphaBlend); spritebatch.draw(texture1, spriteposition1, Color.White); spritebatch.end(); spritebatch.begin(spritesortmode.backtofront, BlendState.AlphaBlend); spritebatch.draw(texture2, spriteposition2, Color.White); spritebatch.end(); base.draw(gametime); 18/34
Wykrywanie kolizji i efekty dźwiękowe protected override void Update(GameTime gametime)... CheckForCollision(); base.update(gametime); 19/34
CheckForCollision() void BoundingBox bb1 = new BoundingBox( new Vector3(spritePosition1.X spriteposition1.y new Vector3(spritePosition1.X + spriteposition1.y + BoundingBox bb2 = new BoundingBox( new Vector3(spritePosition2.X spriteposition2.y new Vector3(spritePosition2.X + spriteposition2.y + (texture1.bounds.width / 2), (texture1.bounds.height / 2), 0), (texture1.bounds.width / 2), (texture1.bounds.height / 2), 0)); (texture2.bounds.width / 2), (texture2.bounds.height / 2), 0), (texture2.bounds.width / 2), (texture2.bounds.height / 2), 0)); if (bb1.intersects(bb2)) soundeffect.play(); spritespeed1.x *= -1; spritespeed1.y *= -1; 20/34
Grafika 3D wprowadzenie Wszystko można zrobić z trójkątów Nie interesuje nas wnętrze bryły 21/34
Grafika 3D wprowadzenie Układy współrzędnych Transformacje układów współrzędnych 22/34
Grafika 3D wprowadzenie Rzutowanie perspektywiczne 23/34
Grafika 3D wprowadzenie Bryła obcinania 24/34
Grafika 3D wprowadzenie Face culling ukrywanie ścianek Bufor Z ukrywanie tego co przesłonięte 25/34
XNA i trójwymiarowość 26/34
XNA i trójwymiarowość public class Game1 : Microsoft.Xna.Framework.Game GraphicsDeviceManager graphics; //SpriteBatch spritebatch; Vector3 cameraposition = new Vector3(0, 20, 50); Vector3 cameratarget = new Vector3(0, 0, 0); Vector3 upvector = new Vector3(0, 1, 0); float fieldofview = 0.4f; Matrix worldmatrix, viewmatrix, projectionmatrix; public float angle = 0f; VertexPositionColor[] trianglevertices; BasicEffect triangleeffect;... 27/34
protected override void LoadContent() //spritebatch = new SpriteBatch(GraphicsDevice); int i = 0; Vector3 punktw = new Vector3(0, 10, 0); Vector3 punkta = new Vector3(-7, 0, 3); Vector3 punktb = new Vector3(7, 0, 3); Vector3 punktc = new Vector3(0, 0, -6); trianglevertices = new VertexPositionColor[12]; trianglevertices[i++] = new VertexPositionColor(punktW, Color.Yellow); trianglevertices[i++] = new VertexPositionColor(punktA, Color.Green); trianglevertices[i++] = new VertexPositionColor(punktC, Color.Green); trianglevertices[i++] = new VertexPositionColor(punktW, Color.Yellow); trianglevertices[i++] = new VertexPositionColor(punktB, Color.Blue); trianglevertices[i++] = new VertexPositionColor(punktC, Color.Blue); trianglevertices[i++] = new VertexPositionColor(punktW, Color.Yellow); trianglevertices[i++] = new VertexPositionColor(punktA, Color.Red); trianglevertices[i++] = new VertexPositionColor(punktB, Color.Red); trianglevertices[i++] = new VertexPositionColor(punktA, Color.Black); trianglevertices[i++] = new VertexPositionColor(punktC, Color.Black); trianglevertices[i++] = new VertexPositionColor(punktB, Color.Black); 28/34
triangleeffect = new BasicEffect(GraphicsDevice); triangleeffect.vertexcolorenabled = true; viewmatrix = Matrix.CreateLookAt(cameraPosition, cameratarget, upvector); projectionmatrix = Matrix.CreatePerspectiveFieldOfView(fieldOfView, GraphicsDevice.Viewport.AspectRatio, 1.0f, 300.0f); 29/34
protected override void Update(GameTime gametime) if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.exit(); angle += (float)(0.3f * gametime.elapsedgametime.totalseconds); base.update(gametime); protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.CornflowerBlue); worldmatrix = Matrix.CreateRotationY(angle); triangleeffect.world = worldmatrix; triangleeffect.view = viewmatrix; triangleeffect.projection = projectionmatrix; // Process each Technique in the Effect. foreach (EffectPass pass in triangleeffect.currenttechnique.passes) pass.apply(); GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, trianglevertices, 0, 4, VertexPositionColor.VertexDeclaration); base.draw(gametime); 30/34
Ukrywanie ścianek? 31/34
Ukrywanie ścianek! trianglevertices[i++] = new VertexPositionColor(punktW, Color.Yellow); trianglevertices[i++] = new VertexPositionColor(punktB, Color.Blue); trianglevertices[i++] = new VertexPositionColor(punktC, Color.Blue); W B C W C B trianglevertices[i++] = new VertexPositionColor(punktW, Color.Yellow); trianglevertices[i++] = new VertexPositionColor(punktC, Color.Blue); trianglevertices[i++] = new VertexPositionColor(punktB, Color.Blue); 32/34
Więcej o grafice 3D 33/34
...i na tym koniec trzeciej części wykładu 34/34