先来看一下游戏的界面
游戏的思路差不多像俄罗斯方块一样,上面的花一直往下掉,然后你就需要选中一只蜜蜂来吃上面的花,当蜜蜂的颜色和花的颜色一样或者花是彩色的花的时候,花就会被蜜蜂给吃掉,这时候这只蜜蜂也会被随机生成一只新的蜜蜂。当吃掉一朵彩色的花的时候,会增加一分,当花落到了底下的时候游戏结束。
看一下下面的代码:
花的对象
Flower.cs
- 游戏的思路差不多像俄罗斯方块一样,上面的花一直往下掉,然后你就需要选中一只蜜蜂来吃上面的花,当蜜蜂的颜色和花的颜色一样或者花是彩色的花的时候,花就会被蜜蜂给吃掉,这时候这只蜜蜂也会被随机生成一只新的蜜蜂。当吃掉一朵彩色的花的时候,会增加一分,当花落到了底下的时候游戏结束。
- 看一下下面的代码:
- 花的对象
- Flower.cs
花的列容器
Column.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Content;
- namespace DemoGame
- {
- class Column
- {
- const int columnTop = 150;//列头高度,当花移动出这个高度后将开始新增新花
- const int numberOfFlowerColors = 6;//花颜色的数量
- const int rainbowFlowerColor = 6; //彩虹花的颜色
- const int flowerDeltaY = 80;
- const int flowerWidth = 72;//花的宽度
- const int flowerHeight = 72;//花的高度
- const int columnBottom = 620;//列的高度 用来判断花是否移动到底了
- private List<Flower> flowers = null;//花的集合
- private SpriteBatch spriteBatch;//绘制花
- private float x;//花的X轴,X轴的坐标是固定的
- private Random r;
- private Texture2D flowerMap;//花的纹理
- public float Velocity = 0.4f;//速度
- /// <summary>
- /// 判断是否有花移动到底
- /// </summary>
- public bool ReachedBottom
- {
- get
- {
- if (flowers.Count != 0 && flowers[0].Y >= columnBottom)
- return true;
- else
- return false;
- }
- }
- /// <summary>
- /// 初始化一列
- /// </summary>
- /// <param name="content">当前的ContentManager</param>
- /// <param name="spriteBatch">当前的SpriteBatch</param>
- /// <param name="x"></param>
- /// <param name="seed"></param>
- public Column(ContentManager content, SpriteBatch spriteBatch, float x, int seed)
- {
- this.spriteBatch = spriteBatch;
- this.x = x;
- this.flowers = new List<Flower>();
- this.r = new Random(seed);
- this.flowerMap = content.Load<Texture2D>("flowermap");
- //初始化 添加3朵花
- AddRandomFlower(x, columnTop + 2 * flowerDeltaY);
- AddRandomFlower(x, columnTop + flowerDeltaY);
- AddRandomFlower(x, columnTop);
- }
- /// <summary>
- /// 随机添加一朵花
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- private void AddRandomFlower(float x, int y)
- {
- int color = r.Next(numberOfFlowerColors+1);
- flowers.Add(new Flower(color, x, y));
- }
- /// <summary>
- /// 在spriteBatch中绘制花精灵
- /// </summary>
- public void Draw()
- {
- foreach (Flower flower in flowers)
- {
- spriteBatch.Draw(flowerMap, new Vector2(flower.X, flower.Y), new Rectangle(flower.Color * flowerWidth, 0, flowerWidth, flowerHeight), Color.White);
- }
- }
- /// <summary>
- /// 更新列
- /// </summary>
- public void Update()
- {
- foreach (Flower f in flowers)
- {
- f.Y += Velocity;//增加Y轴的偏移量,表示正在向下移动
- }
- //如果最上面的花已经全部离开顶部,则需要随机生成新的花从上面下来
- if (flowers.Count == 0 || flowers[flowers.Count - 1].Y > columnTop)
- AddRandomFlower(x, columnTop - flowerDeltaY);
- }
- /// <summary>
- /// 获取最底下的一朵花
- /// </summary>
- /// <returns></returns>
- public Flower GetBottomFlower()
- {
- if (flowers.Count > 0)
- return flowers[0];
- else
- return null;
- }
- /// <summary>
- /// 移走最底下的一朵花
- /// </summary>
- internal void RemoveBottomFlower()
- {
- if (flowers.Count > 0)
- flowers.RemoveAt(0);
- }
- }
- }
蜜蜂对象
Bee.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace DemoGame
- {
- class Bee
- {
- public int Color;//蜜蜂颜色
- public bool IsSelected = false;//是否选中
- public Bee(int color)
- {
- this.Color = color;
- }
- }
- }
蜜蜂容器
BeePicker.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.Xna.Framework.Content;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework;
- namespace DemoGame
- {
- class BeePicker
- {
- const int beeDeltaX = 96;
- const int beeStartX = 5;
- const int beeStartY = 700;
- const int numberOfBeeColors = 5;//蜜蜂颜色的数量
- private List<Bee> bees = null;//蜜蜂集合
- private SpriteBatch spriteBatch;
- private Texture2D beeMap;
- private Random r;
- public BeePicker(ContentManager content, SpriteBatch spriteBatch, int seed)
- {
- beeMap = content.Load<Texture2D>("beemap");
- this.spriteBatch = spriteBatch;
- bees = new List<Bee>();
- r = new Random(seed);
- for (int i = 0; i < 5; i++)
- {
- AddRandomBee();
- }
- }
- /// <summary>
- /// 添加一只蜜蜂
- /// </summary>
- private void AddRandomBee()
- {
- bees.Add(new Bee(r.Next(numberOfBeeColors + 1)));
- }
- /// <summary>
- /// 绘制蜜蜂
- /// </summary>
- public void Draw()
- {
- for (int i = 0; i < 5; i++)
- {
- if(bees[i].IsSelected)
- spriteBatch.Draw(beeMap, new Vector2(beeStartX + i * beeDeltaX, beeStartY), new Rectangle(bees[i].Color * 91, 0, 91, 91), Color.DimGray);
- else
- spriteBatch.Draw(beeMap, new Vector2(beeStartX + i * beeDeltaX, beeStartY), new Rectangle(bees[i].Color * 91, 0, 91, 91), Color.White);
- }
- }
- /// <summary>
- /// 选中一只蜜蜂
- /// </summary>
- /// <param name="x"></param>
- public void MarkSelectedBee(float x)
- {
- GetSelectedBee(x).IsSelected = true;
- }
- /// <summary>
- /// 获取选中的蜜蜂
- /// </summary>
- /// <param name="x"></param>
- /// <returns></returns>
- public Bee GetSelectedBee(float x)
- {
- int index = (int)(x / beeDeltaX);
- return bees[index];
- }
- /// <summary>
- /// 移除和替换蜜蜂
- /// </summary>
- /// <param name="selectedBee"></param>
- /// <param name="availableFlowers"></param>
- public void RemoveAndReplaceBee(Bee selectedBee, List<int> availableFlowers)
- {
- int beeIndex = bees.IndexOf(selectedBee);
- //check if we already have a bee that matches the available flowers
- //remember to skip over the selectedBee since it will be removed in a moment
- bool match = false;
- int rainbowColor = 6;
- //if there is a rainbow flower it will always match
- if (availableFlowers.Contains(rainbowColor))
- match = true;
- else
- {
- for (int i = 0; i < bees.Count; i++)
- {
- if(i != beeIndex && availableFlowers.Contains(bees[i].Color)){
- match = true;
- break;
- }
- }
- }
- int color;
- if(match){
- //we already have a match, just add a random colored bee
- color = r.Next(numberOfBeeColors + 1 );
- }
- else{
- //we have no match so we must pick a color from the available colors
- color = availableFlowers[r.Next(availableFlowers.Count)];
- }
- //set the selected bee to the new color to "create" a new bee
- bees[beeIndex].Color = color;
- }
- internal void DeselectAll()
- {
- foreach (Bee bee in bees)
- bee.IsSelected = false;
- }
- }
- }
游戏主程序
Game1.cs
- 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.Input.Touch;
- using Microsoft.Xna.Framework.Media;
- namespace DemoGame
- {
- /// <summary>
- /// This is the main type for your game
- /// </summary>
- public class Game1 : Microsoft.Xna.Framework.Game
- {
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- //纹理
- Texture2D backgroundTexture;
- Texture2D foregroundTexture;
- Texture2D hudTexture;
- Texture2D flowerMapTexture;
- //分数
- int score = 0;
- //字体
- SpriteFont largeFont;
- SpriteFont mediumFont;
- SpriteFont smallFont;
- List<Column> columns;//列集合
- bool gameOver = false;//标记游戏是否结束
- BeePicker beePicker = null;//蜜蜂处理类
- Bee selectedBee = null;//蜜蜂
- public Game1()
- {
- graphics = new GraphicsDeviceManager(this);
- //设置游戏图像的宽和高
- graphics.PreferredBackBufferHeight = 800;
- graphics.PreferredBackBufferWidth = 480;
- Content.RootDirectory = "Content";
- // Frame rate is 30 fps by default for Windows Phone.
- TargetElapsedTime = TimeSpan.FromTicks(333333);
- // Extend battery life under lock.
- InactiveSleepTime = TimeSpan.FromSeconds(1);
- }
- /// <summary>
- /// 初始化
- /// </summary>
- protected override void Initialize()
- {
- // TODO: Add your initialization logic here
- //添加触摸事件
- TouchPanel.EnabledGestures = GestureType.Tap;
- base.Initialize();
- }
- /// <summary>
- /// 加载资源
- /// </summary>
- protected override void LoadContent()
- {
- //创建一个新的SpriteBatch用来绘制纹理
- spriteBatch = new SpriteBatch(GraphicsDevice);
- //加载纹理
- backgroundTexture = Content.Load<Texture2D>("GameScreenBackground");
- foregroundTexture = Content.Load<Texture2D>("GameScreenForeground");
- hudTexture = Content.Load<Texture2D>("HUDBackground");
- flowerMapTexture = Content.Load<Texture2D>("flowermap");
- //加载字体资源
- largeFont = Content.Load<SpriteFont>("LargeMenuFont");
- mediumFont = Content.Load<SpriteFont>("MediumMenuFont");
- smallFont = Content.Load<SpriteFont>("SmallMenuFont");
- //初始化列
- InitializeColumns();
- beePicker = new BeePicker(Content, spriteBatch, System.DateTime.Now.Millisecond);
- }
- /// <summary>
- /// 初始化列
- /// </summary>
- private void InitializeColumns()
- {
- columns = new List<Column>();
- int seed = System.DateTime.Now.Millisecond;
- //初始化6列
- for (int i = 0; i < 5; i++)
- {
- columns.Add(new Column(Content, spriteBatch, i * 92 + 22, seed + i));
- }
- }
- /// <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>
- protected override void Update(GameTime gameTime)
- {
- // 退出游戏
- if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
- this.Exit();
- // 添加更新的逻辑
- if (!gameOver)
- {
- //处理用户的操作
- while (TouchPanel.IsGestureAvailable)//是否触摸到屏幕
- {
- GestureSample gesture = TouchPanel.ReadGesture();//获取手势
- if (gesture.GestureType == GestureType.Tap)//点击操作
- {
- HandleInput(gesture.Position);//传入点击的位置,处理点击操作
- }
- }
- //更新花的状态,即不停地往下移动
- foreach (Column c in columns)
- {
- c.Update();
- if (c.ReachedBottom)//花到达底部,游戏结束
- {
- gameOver = true;
- break;
- }
- }
- }
- base.Update(gameTime);
- }
- /// <summary>
- /// 点击输入操作处理
- /// </summary>
- /// <param name="position"></param>
- private void HandleInput(Vector2 position)
- {
- if (position.X > 0 && position.X < 480 && position.Y > 700 && position.Y < 800)//点种了蜜蜂的位置
- HandleBeeSelection(position.X);
- else if (selectedBee != null)//选中了蜜蜂
- HandleFlowerSelection(position.X, position.Y);
- }
- /// <summary>
- /// 处理选中花的操作
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- private void HandleFlowerSelection(float x, float y)
- {
- //判断是否点中了列的位置
- if (x > 10 && x < 470 && y > 100 && y < 700)
- {
- int rainbowColor = 6;
- int selectedColumnIndex = (int)((x - 10) / 92);
- //获取点中的列
- Column selectedColumn = columns[selectedColumnIndex];
- //获取点中的列底部的花
- Flower selectedFlower = selectedColumn.GetBottomFlower();
- //判断是否点中了底部的花,并且花的颜色和蜜蜂的颜色要相等,或者花是彩色的花
- if(selectedFlower != null && (selectedFlower.Color == selectedBee.Color || selectedFlower.Color == rainbowColor))
- {
- //移除花
- selectedColumn.RemoveBottomFlower();
- //替换另外一只蜜蜂,并且要保证至少要有一只蜜蜂可以和最底层的花可以匹配得上
- List<int> availableFlowers = GetAvailableFlowers();
- beePicker.RemoveAndReplaceBee(selectedBee, availableFlowers);
- //取消对蜜蜂的选中状态
- beePicker.DeselectAll();
- selectedBee = null;//设置选中的蜜蜂为null
- //如果蜜蜂吃掉的是彩色的花则增加一分
- if (selectedFlower.Color == rainbowColor)
- {
- score++;
- //如果分数达到10, 20, 30... 则不断地增加花下落的Y轴偏移量速度
- if ((score % 10) == 0)
- {
- foreach (Column c in columns)
- c.Velocity += 0.1f;
- }
- }
- }
- }
- }
- /// <summary>
- /// 获取最底下花的颜色,用来作为随机生成蜜蜂的一个条件
- /// </summary>
- /// <returns></returns>
- private List<int> GetAvailableFlowers()
- {
- List<int> flowerColors = new List<int>();
- foreach (Column c in columns)
- {
- Flower f = c.GetBottomFlower();
- if (f != null)
- flowerColors.Add(f.Color);
- }
- return flowerColors;
- }
- /// <summary>
- /// 处理选中蜜蜂操作
- /// </summary>
- /// <param name="x"></param>
- private void HandleBeeSelection(float x)
- {
- //first de-select any previously selected bee
- if (selectedBee != null)
- {
- selectedBee.IsSelected = false;
- selectedBee = null;
- }
- //Mark and select the new bee
- beePicker.MarkSelectedBee(x);
- selectedBee = beePicker.GetSelectedBee(x);
- }
- /// <summary>
- /// This is called when the game should draw itself.
- /// </summary>
- /// <param name="gameTime">Provides a snapshot of timing values.</param>
- protected override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- spriteBatch.Begin();
- //画游戏背景
- spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
- //判断游戏是否结束
- if (!gameOver)
- {
- //绘制花精灵
- foreach (Column c in columns)
- c.Draw();
- //绘制蜜蜂精灵
- beePicker.Draw();
- }
- else
- {
- spriteBatch.DrawString(largeFont, "GAME OVER", new Vector2(150, 400), Color.Red);
- }
- spriteBatch.Draw(foregroundTexture, Vector2.Zero, Color.White);
- DrawHUD();
- spriteBatch.End();
- base.Draw(gameTime);
- }
- /// <summary>
- /// 初始化屏幕
- /// </summary>
- private void DrawHUD()
- {
- spriteBatch.Draw(hudTexture, new Vector2(7, 7), Color.White);
- //Print out game score and level
- spriteBatch.DrawString(mediumFont, "Marathon", new Vector2(40, 10), Color.Blue);
- spriteBatch.DrawString(largeFont, score.ToString(), new Vector2(127, 45), Color.Yellow);
- //TODO: Draw a flower on the HUD
- spriteBatch.Draw(flowerMapTexture, new Vector2(40, 45), new Rectangle(6*72, 0, 72, 72), Color.White, 0, Vector2.Zero, 0.5f, SpriteEffects.None, 0f);
- //Print out instructions
- spriteBatch.DrawString(smallFont, "Match flowers and bees", new Vector2(210, 10), Color.Yellow);
- spriteBatch.DrawString(smallFont, "Rainbow flowers match", new Vector2(206, 30), Color.Yellow);
- spriteBatch.DrawString(smallFont, "with all bees", new Vector2(260, 50), Color.Yellow);
- //Print out goal message
- spriteBatch.DrawString(largeFont, "Collect Rainbow Flowers", new Vector2(50, 115), Color.Blue);
- }
- }
- }
游戏的项目结构
本文转自linzheng 51CTO博客,原文链接:http://blog.51cto.com/linzheng/1078403