using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Jin_sPong
{
public class Game1 : Microsoft.Xna.Framework.Game
{
enum GameMode
{ Menu, Game, GameOver }
GameMode gameMode = GameMode.Menu;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
int currentMenuItem = 0;
int leftPlayerLives = 3, rightPlayerLives = 3; // 목숨 갯수
float leftPaddlePosition = 0.5f, rightPaddlePosition = 0.5f; // 현재 paddle 위치
bool remUpPressed = false,
remDownPressed = false,
remEnterPressed = false,
remEscPressed = false;
int delay = 50;
int dindex = 0;
AudioEngine audioEngine;
WaveBank waveBank;
SoundBank SoundBank;
Vector2 ballSpeedVector = new Vector2(0, 0); // 공 이동 방향
Vector2 ballPosition = new Vector2(0.5f, 0.5f); // 현재 공의 위치
delegate void TestDelegate();
//---------------------------------
const float BallSpeedMultiplicator = 0.5f;
const float ComputerPaddleSpeed = 0.5f;
bool multiplayer = false;
//--------------------------------
static Rectangle[] GameItemRect;
public void ShowLives()
{ // Left players lives
RenderSprite(menuTexture, 2, 2, GameLivesRect);
for (int num = 0; num < leftPlayerLives; num++)
RenderSprite(gameTexture,
2 + GameLivesRect.Width + GameSmallBallRect.Width * num - 2, 9,
GameSmallBallRect);
// Right players lives
int rightX = 1024 - GameLivesRect.Width - GameSmallBallRect.Width * 3 - 4;
RenderSprite(menuTexture, rightX, 2, GameLivesRect);
for (int num = 0; num < rightPlayerLives; num++)
RenderSprite(gameTexture,
rightX + GameLivesRect.Width + GameSmallBallRect.Width * num - 2, 9, GameSmallBallRect);
}
public void RenderBall()
{
RenderSprite(gameTexture,
(int)((0.05f + 0.9f * ballPosition.X) * 1024) - GameBallRect.Width / 2,
(int)((0.02f + 0.96f * ballPosition.Y) * 768) - GameBallRect.Height / 2,
GameBallRect);
}
public void RenderPaddles()
{
// left Paddles
RenderSprite(gameTexture,
(int)(0.05f * 1024) - GameRedPaddleRect.Width / 2,
(int)((0.06f + 0.88f * leftPaddlePosition) * 768) - GameRedPaddleRect.Height / 2,
GameRedPaddleRect);
// Right Paddles
RenderSprite(gameTexture,
(int)(0.95f * 1024) - GameBluePaddleRect.Width / 2,
(int)((0.06f + 0.88f * rightPaddlePosition) * 768) - GameBluePaddleRect.Height / 2,
GameBluePaddleRect);
}
class TestPongGame : Game1
{
TestDelegate testLoop;
public TestPongGame(TestDelegate setTestLoop)
{
testLoop = setTestLoop;
} // TestPongGame(setTestLoop)
protected override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
testLoop();
} // Draw(gameTime)
} // class TestPongGame
static TestPongGame testGame;
static void StartTest(TestDelegate testLoop)
{
using (testGame = new TestPongGame(testLoop))
{
testGame.Run();
}
}
public static void TestBallCollisions()
{
StartTest(
delegate
{
// Make sure we are in the game and in singleplayer mode
testGame.multiplayer = false;
testGame.Window.Title = "Xna Pong - Press 1-5 to start collision tests";//타이틀주기
// Start specific collision scene based on the user input.
if (testGame.keyboard.IsKeyDown(Keys.D1))//1눌렀을때
{
// 첫번째로 스크린보더와충돌했는지체크
testGame.ballPosition = new Vector2(0.6f, 0.9f);
testGame.ballSpeedVector = new Vector2(1, 1);
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D2))
{
// Second test, straight on collision with right paddle
testGame.ballPosition = new Vector2(0.5f, 0.2f);//공의 위치
testGame.ballSpeedVector = new Vector2(-1, -1f);//왼쪽방향
testGame.rightPaddlePosition = 0.7f;//오른쪽패들의위치
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D3))
{
// Thrid test, straight on collision with left paddle
testGame.ballPosition = new Vector2(0.5f, 0.5f);
testGame.ballSpeedVector = new Vector2(1, -0.5f);
testGame.rightPaddlePosition = 0.25f;//값이 내려갈수록 위
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D4))
{
// Advanced test to check if we hit the edge of the right paddle
testGame.ballPosition = new Vector2(0.9f, 0.4f);
testGame.ballSpeedVector = new Vector2(1, -0.5f);
testGame.rightPaddlePosition = 0.29f;
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D5))
{
// Advanced test to check if we hit the edge of the right paddle
testGame.ballPosition = new Vector2(0.9f, 0.4f);
testGame.ballSpeedVector = new Vector2(1, -0.5f);
testGame.rightPaddlePosition = 0.42f;
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D6))//왼쪽패들충돌
{
// Advanced test to check if we hit the edge of the right paddle
testGame.ballPosition = new Vector2(0.7f, 0.9f);
testGame.ballSpeedVector = new Vector2(-1, -0.5f);
testGame.rightPaddlePosition = 0.42f;
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D7))//왼쪽 패들 아래 에지 충돌
{
// Advanced test to check if we hit the edge of the right paddle
testGame.ballPosition = new Vector2(0.3f, 0.2f);
testGame.ballSpeedVector = new Vector2(-1, -1f);
testGame.rightPaddlePosition = 0.7f;
} // if
else if (testGame.keyboard.IsKeyDown(Keys.D8))//왼쪽 패들 위 충돌
{
// Advanced test to check if we hit the edge of the right paddle
testGame.ballPosition = new Vector2(0.3f, 0.9f);
testGame.ballSpeedVector = new Vector2(-1, 0.5f);
testGame.rightPaddlePosition = 0.42f;
} // if
// Show lives
testGame.ShowLives();
// Ball in center
testGame.RenderBall();
// Render both paddles
testGame.RenderPaddles();
}); //End of StartTest
} // TestBallCollisions()
public static void TestMenuSprites(){
StartTest(
delegate
{
testGame.RenderSprite(testGame.menuTexture, 512 - XnaPongLogoRect.Width / 2, 150, XnaPongLogoRect);
testGame.RenderSprite(testGame.menuTexture, 512 - MenuSingleplayerRect.Width / 2, 300, MenuSingleplayerRect, testGame.currentMenuItem == 0 ? Color.Orange : Color.White);//
testGame.RenderSprite(testGame.menuTexture, 512 - MenuMultiplayerRect.Width / 2, 350, MenuMultiplayerRect, testGame.currentMenuItem == 1 ? Color.Orange : Color.White);
testGame.RenderSprite(testGame.menuTexture, 512 - MenuExitRect.Width / 2, 400, MenuExitRect, testGame.currentMenuItem == 2 ? Color.Orange : Color.White);
});
}
public class SpriteToRender//스프라이트목록에 스프라이트추가->drawsprite에서 그림
{
public Texture2D texture;
public Rectangle rect;
public Rectangle? sourceRect;
public Color color;
public SpriteToRender(Texture2D setTexture, Rectangle setRect,
Rectangle? setSourceRect, Color setColor)
{
texture = setTexture;
rect = setRect;
sourceRect = setSourceRect;
color = setColor;
}
}
List<SpriteToRender> sprites = new List<SpriteToRender>();
public static void TestSounds()
{
StartTest(
delegate
{
if (testGame.keyboard.IsKeyDown(Keys.Space))
testGame.SoundBank.PlayCue("PongBallHit");
if (testGame.keyboard.IsKeyDown(Keys.LeftControl))
testGame.SoundBank.PlayCue("PongBallLost");
});
} // TestSounds()
public static void TestGameSprites()
{
StartTest(
delegate
{
testGame.ShowLives(); //생명 표시
testGame.RenderBall();
testGame.RenderPaddles();
});
}
void RenderSprite(Texture2D texture, int x, int y, Rectangle sourceRect, Color color)
{
RenderSprite(texture, new Rectangle(x, y, sourceRect.Width, sourceRect.Height), sourceRect, color);
}
public void RenderSprite(Texture2D texture, Rectangle rect, Rectangle? sourceRect, Color color)
{
sprites.Add(new SpriteToRender(texture, rect, sourceRect, color));
}
void RenderSprite(Texture2D texture, int x, int y, Rectangle sourceRect)//어떤텍스쳐를 어떠위치에 source를 어느부분에서 가져올것인가
{
RenderSprite(texture,
new Rectangle(x, y, sourceRect.Width, sourceRect.Height), sourceRect, Color.White);
}
public void DrawSprites()
{
if (sprites.Count == 0) return;//등록된 스프라이트가있는가?
spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
SpriteSortMode.BackToFront,
SaveStateMode.None);
foreach (SpriteToRender sprite in sprites)//sprite에 모든엘리먼트를 그려라
spriteBatch.Draw(sprite.texture,
new Rectangle(sprite.rect.X * width / 1024, sprite.rect.Y * height / 768,
sprite.rect.Width * width / 1024, sprite.rect.Height * height / 768),
sprite.sourceRect, sprite.color);
spriteBatch.End();
sprites.Clear();
}
int ItemIndex = 0;
int width;
int height;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
///
Texture2D backgroundTexture, menuTexture, gameTexture;
Texture2D ItemTexture1;
Texture2D ItemTexture2;
SpriteBatch spritesBatch;
protected override void Initialize()
{
// TODO: Add your initialization logic here
backgroundTexture = Content.Load<Texture2D>("SpaceBackground");
menuTexture = Content.Load<Texture2D>("PongMenu");
gameTexture = Content.Load<Texture2D>("PongGame");
ItemTexture1 = Content.Load<Texture2D>("1");
ItemTexture2 = Content.Load<Texture2D>("2");
int index = 0, ww =3;
GameItemRect = new Rectangle[16];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
GameItemRect[index++] = new Rectangle(j *ww, i * ww, 100,100);
audioEngine = new AudioEngine("Content\\PongSound.xgs");
waveBank = new WaveBank(audioEngine, "Content\\Wave Bank.xwb");
if (waveBank != null)
SoundBank = new SoundBank(audioEngine, "Content\\Sound Bank.xsb");
spritesBatch = new SpriteBatch(graphics.GraphicsDevice);
width = graphics.GraphicsDevice.Viewport.Width;
height = graphics.GraphicsDevice.Viewport.Height;
RenderSprite(menuTexture, 512 - XnaPongLogoRect.Width / 2, 150, XnaPongLogoRect);
RenderSprite(menuTexture, 512 - MenuSingleplayerRect.Width / 2, 300, MenuSingleplayerRect,currentMenuItem == 0 ? Color.Orange : Color.White);
RenderSprite(menuTexture, 512 - MenuMultiplayerRect.Width / 2, 350, MenuMultiplayerRect, currentMenuItem == 1 ? Color.Orange : Color.White);
RenderSprite(menuTexture, 512 - MenuExitRect.Width / 2, 400, MenuExitRect, currentMenuItem == 2 ? Color.Orange : Color.White);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
///
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
///
KeyboardState keyboard;
protected override void Update(GameTime gameTime)
{
remUpPressed = keyboard.IsKeyDown(Keys.Up);
remDownPressed = keyboard.IsKeyDown(Keys.Down);
remEscPressed = keyboard.IsKeyDown(Keys.Escape);
keyboard = Keyboard.GetState();
float moveFactorPerSecond = 0.5f *
(float)gameTime.ElapsedRealTime.TotalMilliseconds / 1000.0f;
if (ballSpeedVector.X == 0 && ballSpeedVector.Y == 0)
StartNewBall();
ballPosition += ballSpeedVector * moveFactorPerSecond * BallSpeedMultiplicator;
if (keyboard.IsKeyDown(Keys.Up))
rightPaddlePosition -= moveFactorPerSecond;
if (keyboard.IsKeyDown(Keys.Down))
rightPaddlePosition += moveFactorPerSecond;
if (multiplayer)
{
// Move up and down if we press the cursor or gamepad keys.
if (keyboard.IsKeyDown(Keys.W))
leftPaddlePosition -= moveFactorPerSecond;
if (keyboard.IsKeyDown(Keys.S) ||
keyboard.IsKeyDown(Keys.O))
leftPaddlePosition += moveFactorPerSecond;
} // if
else
{
// Just let the computer follow the ball position
float computerChange = ComputerPaddleSpeed * moveFactorPerSecond;
if (leftPaddlePosition > ballPosition.Y + computerChange)
leftPaddlePosition -= computerChange;//bp가 pd낮으면 아래에위치(공을 쫓아가도록)
else if (leftPaddlePosition < ballPosition.Y - computerChange)
leftPaddlePosition += computerChange;
//bp가 pd보다크면 위에위치
}
if (leftPaddlePosition < 0)
leftPaddlePosition = 0;
if (leftPaddlePosition > 1)
leftPaddlePosition = 1;
if (rightPaddlePosition < 0)
rightPaddlePosition = 0;
if (rightPaddlePosition > 1)
rightPaddlePosition = 1;
if (ballPosition.Y < 0 || ballPosition.Y > 1)
{
SoundBank.PlayCue("PongBallHit");
ballSpeedVector.Y = -ballSpeedVector.Y;
// 공을 다시 화면 공간 안으로 넣는다.
if (ballPosition.Y < 0) ballPosition.Y = 0;
if (ballPosition.Y > 1) ballPosition.Y = 1;
} // if
Vector2 ballSize = new Vector2(
GameBallRect.Width / 1024.0f, GameBallRect.Height / 768.0f);
BoundingBox ballBox = new BoundingBox(
new Vector3(ballPosition.X - ballSize.X / 2, ballPosition.Y - ballSize.Y / 2, 0),
new Vector3(ballPosition.X + ballSize.X / 2, ballPosition.Y + ballSize.Y / 2, 0));
BoundingBox ribbonbox = new BoundingBox(
new Vector3(ballPosition.X - ballSize.X / 2, ballPosition.Y - ballSize.Y / 2, 0),
new Vector3(ballPosition.X + ballSize.X / 2, ballPosition.Y + ballSize.Y / 2, 0));
Vector2 paddleSize = new Vector2(
GameRedPaddleRect.Width / 1024.0f, GameRedPaddleRect.Height / 768.0f);
BoundingBox leftPaddleBox = new BoundingBox(
new Vector3(-paddleSize.X / 2, leftPaddlePosition - paddleSize.Y / 2, 0),
new Vector3(+paddleSize.X / 2, leftPaddlePosition + paddleSize.Y / 2, 0));
BoundingBox rightPaddleBox = new BoundingBox(
new Vector3(1 - paddleSize.X / 2, rightPaddlePosition - paddleSize.Y / 2, 0),
new Vector3(1 + paddleSize.X / 2, rightPaddlePosition + paddleSize.Y / 2, 0));
if (ballBox.Intersects(leftPaddleBox))
{
// Bounce of the paddle (always make positive)
ballSpeedVector.X = Math.Abs(ballSpeedVector.X);
// Increase speed a little
ballSpeedVector *= 1.05f;
// Did we hit the edges of the paddle?
if (ballBox.Intersects(new BoundingBox(
new Vector3(leftPaddleBox.Min.X - 0.01f, leftPaddleBox.Min.Y - 0.01f, 0),
new Vector3(leftPaddleBox.Min.X + 0.01f, leftPaddleBox.Min.Y + 0.01f, 0))))
// Bounce of at a more difficult angle for the other player
ballSpeedVector.Y = -2;
else if (ballBox.Intersects(new BoundingBox(
new Vector3(leftPaddleBox.Min.X - 0.01f, leftPaddleBox.Max.Y - 0.01f, 0),
new Vector3(leftPaddleBox.Min.X + 0.01f, leftPaddleBox.Max.Y + 0.01f, 0))))
// Bounce of at a more difficult angle for the other player
ballSpeedVector.Y = +2;
SoundBank.PlayCue("PongBallHit");
} // if
if (ballBox.Intersects(rightPaddleBox))
{
// Bounce of the paddle (always make negative)
ballSpeedVector.X = -Math.Abs(ballSpeedVector.X);
// Increase speed a little
ballSpeedVector *= 1.05f;
// Did we hit the edges of the paddle?
if (ballBox.Intersects(new BoundingBox(
new Vector3(rightPaddleBox.Min.X - 0.01f, rightPaddleBox.Min.Y - 0.01f, 0),
new Vector3(rightPaddleBox.Min.X + 0.01f, rightPaddleBox.Min.Y + 0.01f, 0))))//패들박스 위에 충돌했을때
// Bounce of at a more difficult angle for the other player
ballSpeedVector.Y = -2;//각도를 -2
else if (ballBox.Intersects(new BoundingBox(
new Vector3(rightPaddleBox.Min.X - 0.01f, rightPaddleBox.Max.Y - 0.01f, 0),
new Vector3(rightPaddleBox.Min.X + 0.01f, rightPaddleBox.Max.Y + 0.01f, 0))))
// Bounce of at a more difficult angle for the other player
ballSpeedVector.Y = +2;
SoundBank.PlayCue("PongBallHit");
} // if
if (ribbonbox.Intersects(ballBox))
{
ballSpeedVector.X = Math.Abs(ballSpeedVector.X);
}
if (ballPosition.X < -0.065f)
{
// Reduce number of lives
SoundBank.PlayCue("PongBallLost");
leftPlayerLives--;
// Start new ball
StartNewBall();
} // if
else if (ballPosition.X > 1.065f)
{
SoundBank.PlayCue("PongBallLost");
// Reduce number of lives
rightPlayerLives--;
// Start new ball
StartNewBall();
} // if
if (gameMode == GameMode.Game &&
(leftPlayerLives == 0 || rightPlayerLives == 0))
{
//gameMode = GameMode.GameOver;
StopBall();
} // if
if (gameMode == GameMode.Menu)
{
if (keyboard.IsKeyDown(Keys.Down) && remDownPressed == false) currentMenuItem = (currentMenuItem + 1) % 3;
else if (keyboard.IsKeyDown(Keys.Up) && remUpPressed == false) currentMenuItem = (currentMenuItem + 2) % 3;
else if (keyboard.IsKeyDown(Keys.Enter) && remEnterPressed == false)
{
switch (currentMenuItem)
{
case 0: multiplayer = false; break;
case 1: multiplayer = true; break;
case 2: this.Exit(); break;
}
gameMode = GameMode.Game;
}
else if (keyboard.IsKeyDown(Keys.Escape) && remEscPressed == false) this.Exit();
}
else
{
if (keyboard.IsKeyDown(Keys.Escape)) gameMode = GameMode.Menu;
}
if (leftPlayerLives == 0 || rightPlayerLives == 0)
{
StopBall();
} // if
base.Update(gameTime);
}
public void StopBall()
{
ballPosition = new Vector2(0.5f, 0.5f);
ballSpeedVector.X = ballSpeedVector.Y = 0;
}
public void StartNewBall()
{
ballPosition = new Vector2(0.5f, 0.5f);
Random rnd = new Random((int)DateTime.Now.Ticks);
int direction = rnd.Next(4);
ballSpeedVector = direction == 0 ? new Vector2(1, 0.8f) :
direction == 1 ? new Vector2(1, -0.8f) :
direction == 2 ? new Vector2(-1, 0.8f) :
new Vector2(-1, -0.8f);
} // StartNewBall()
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
///
public void RenderItem(int number)
{
RenderSprite(ItemTexture1, (int)(0.25 * 1024), (int)(0.35 * 768), GameItemRect[ItemIndex]);
if (number == 0) ItemIndex = (ItemIndex + 1) % 16;
RenderSprite(ItemTexture2, (int)(0.7 * 1024), (int)(0.7 * 768), GameItemRect[ItemIndex]);
if (number == 0) ItemIndex = (ItemIndex + 1) % 16;
}
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, width, height), Color.LightGray);
spriteBatch.End();
if (gameMode == GameMode.Menu)
{
RenderSprite(menuTexture, 512 - XnaPongLogoRect.Width / 2, 150, XnaPongLogoRect);
RenderSprite(menuTexture, 512 - MenuSingleplayerRect.Width / 2, 300, MenuSingleplayerRect,
currentMenuItem == 0 ? Color.Orange : Color.White);
RenderSprite(menuTexture, 512 - MenuMultiplayerRect.Width / 2, 350, MenuMultiplayerRect,
currentMenuItem == 1 ? Color.Orange : Color.White);
RenderSprite(menuTexture, 512 - MenuExitRect.Width / 2, 400, MenuExitRect,
currentMenuItem == 2 ? Color.Orange : Color.White);
}
else if (gameMode == GameMode.Game)
{
RenderItem((dindex++) % delay);
ShowLives();
RenderBall();
RenderPaddles();
}
DrawSprites();
/*
Vector2 spritePosition = Vector2.Zero;
Rectangle targetRect = new Rectangle(0, 0, width, 375);
Rectangle sourceRect = new Rectangle(-170, -150, width, 375);
spriteBatch.Draw(menuTexture, targetRect, sourceRect, Color.White);
spritesBatch.End(); // TODO: Add your drawing code here
spriteBatch.End();*/
base.Draw(gameTime);
}
static readonly Rectangle
XnaPongLogoRect = new Rectangle(0, 0, 512, 110),
MenuSingleplayerRect = new Rectangle(0, 110, 512, 38),
MenuMultiplayerRect = new Rectangle(0, 148, 512, 38),
MenuExitRect = new Rectangle(0, 185, 512, 38),
GameLivesRect = new Rectangle(0, 222, 100, 34),
GameRedWonRect = new Rectangle(151, 222, 155, 34),
GameBlueWonRect = new Rectangle(338, 222, 165, 34),
GameRedPaddleRect = new Rectangle(23, 0, 22, 92),
GameBluePaddleRect = new Rectangle(0, 0, 22, 92),
GameBallRect = new Rectangle(1, 94, 33, 33),
GameSmallBallRect = new Rectangle(37, 108, 19, 19);//사용시전역변수로 선언(여러번사용하니까)
}
}
'Not Using > game' 카테고리의 다른 글
11.18 beakout (0) | 2009.11.18 |
---|---|
esc누르면 메뉴화면으로.. 애니메이션넣기는 미완성; (0) | 2009.11.10 |
게임제작 (0) | 2009.10.14 |
과제(live, paddle, ball) (0) | 2009.10.11 |
10.07 Live, ball, paddle (0) | 2009.09.16 |