XNA游戏:Bizzy Bees蜜蜂警官游戏

先来看一下游戏的界面

done

游戏的思路差不多像俄罗斯方块一样,上面的花一直往下掉,然后你就需要选中一只蜜蜂来吃上面的花,当蜜蜂的颜色和花的颜色一样或者花是彩色的花的时候,花就会被蜜蜂给吃掉,这时候这只蜜蜂也会被随机生成一只新的蜜蜂。当吃掉一朵彩色的花的时候,会增加一分,当花落到了底下的时候游戏结束。

 

看一下下面的代码:

花的对象

Flower.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DemoGame
{
    class Flower
    {
        public int Color;//颜色
        public float X;//X轴坐标
        public float Y;//Y轴坐标

        public Flower(int color, float x, float y)
        {
            this.Color = color;
            this.X = x;
            this.Y = y;
        }
    }
}

花的列容器

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);
        }
    }
}

 

游戏的项目结构

 

参考文章:

http://blogs.msdn.com/b/tess/archive/2012/03/02/xna-for-windows-phone-walkthrough-creating-the-bizzy-bees-game.aspx

posted on 2012-04-10 23:20  linzheng  阅读(985)  评论(0编辑  收藏  举报

导航