一、游戏分析
相信大家对金山打字通、打字精灵等打字软件非常熟悉,想当年刚接触计算机时还靠它们的打字游戏练习打字基本功。这章的游戏DEMO就是一个打字小游戏,当然,它很简单,只是A~Z字母的打字练习小游戏。游戏的设计也不复杂,游戏开始时先初始化下落字母的个数和每次下落字母的概率,随着时间的进行,字母会从界面上方逐渐下落到界面底下,在这过程中你需要敲击键盘上与界面下落的字母相对应的键位,如果键位的字母与下落的字母一致,则记录打字正确数量,否则不记录,无论如何,敲击一次键盘记录一下敲击键盘数,当字母下落到界面底下时,字母停止下落,该字母被视为无效,相应地,也记录一次敲击数。正确率、敲击数等信息会在界面上显示,游戏还有倒计时,时间一到则被视为游戏结束。
先定义一个字母表,字母表的实现为:
///LetterTable类实现
- using System;
- namespace Typing
- {
- internal sealed class LetterTable
- {
- private static String[] LETTERS_TABLE =
- {
- "A", "B", "C", "D", "E", "F", "G",
- "H", "I", "J", "K", "L", "M", "N",
- "O", "P", "Q", "R", "S", "T", "U",
- "V", "W", "X", "Y", "Z"
- };
- /// <summary>
- /// 获取字母表长度
- /// </summary>
- /// <returns></returns>
- public static Int32 getLength()
- {
- return LETTERS_TABLE.Length;
- }
- /// <summary>
- /// 根据索引获取字母
- /// </summary>
- /// <param name="index"></param>
- /// <returns></returns>
- public static String getLetter(Int32 index)
- {
- return LETTERS_TABLE[index];
- }
- /// <summary>
- /// 根据字母获取字母码
- /// </summary>
- /// <param name="letter"></param>
- /// <returns></returns>
- public static Int32 getLetterCode(String letter)
- {
- Int32 code = 65;
- for (Int32 i = 0; i < LETTERS_TABLE.Length; i++)
- {
- if (getLetter(i).Equals(letter))
- {
- code = 65 + i;
- }
- }
- return code;
- }
- }
- }
///Letter类实现
- using System;
- using CEngine;
- using CGraphics;
- namespace Typing
- {
- internal class Letter
- {
- /// <summary>
- /// 字母
- /// </summary>
- private String m_letter;
- /// <summary>
- /// 字母码
- /// </summary>
- private Int32 m_code;
- /// <summary>
- /// 字母背景色
- /// </summary>
- private ConsoleColor m_backcolor;
- /// <summary>
- /// 字母前景色
- /// </summary>
- private ConsoleColor m_fontcolor;
- /// <summary>
- /// 字母活动情况
- /// </summary>
- private Boolean m_bAlive;
- /// <summary>
- /// 字母窗体位置
- /// </summary>
- private CPoint m_position;
- /// <summary>
- /// 随机数
- /// </summary>
- private static Random m_random = new Random();
- /// <summary>
- /// 构造函数
- /// </summary>
- public Letter()
- {
- }
- public String getLetter()
- {
- return this.m_letter;
- }
- public void setLetter(String letter)
- {
- this.m_letter = letter;
- }
- public Int32 getCode()
- {
- return this.m_code;
- }
- public void setCode(Int32 code)
- {
- this.m_code = code;
- }
- public Char getChar()
- {
- return (Char)this.m_code;
- }
- public ConsoleColor getBackcolor()
- {
- return this.m_backcolor;
- }
- public ConsoleColor getFontcolor()
- {
- return this.m_fontcolor;
- }
- public void setBackcolor(ConsoleColor color)
- {
- this.m_backcolor = color;
- }
- public void setFontcolor(ConsoleColor color)
- {
- this.m_fontcolor = color;
- }
- public Boolean getAlive()
- {
- return m_bAlive;
- }
- public void setAlive(Boolean bAlive)
- {
- this.m_bAlive = bAlive;
- }
- public CPoint getPosition()
- {
- return this.m_position;
- }
- public void setPosition(CPoint point)
- {
- this.m_position = point;
- }
- public void setPosition(Int32 x, Int32 y)
- {
- this.m_position.setX(x);
- this.m_position.setY(y);
- }
- /// <summary>
- /// 随机得到一个字母
- /// </summary>
- public void newLetter()
- {
- setLetter(LetterTable.getLetter(m_random.Next(0, 26)));
- setCode(LetterTable.getLetterCode(getLetter()));
- setBackcolor((ConsoleColor)m_random.Next(0, 16));
- setFontcolor((ConsoleColor)(15 - (Int32)getBackcolor()));
- setPosition(m_random.Next(1, 30), -1);
- setAlive(false);
- }
- /// <summary>
- /// 绘制字母
- /// </summary>
- /// <param name="draw"></param>
- public void draw(CDraw draw)
- {
- if (m_bAlive)
- {
- draw.setBackcolor(this.m_backcolor);
- draw.drawText(m_letter, m_position.getX(), m_position.getY(), 1, 1, this.m_fontcolor);
- }
- draw.setDrawSymbol(CSymbol.DEFAULT);
- draw.fillRect(m_position.getX(), m_position.getY() - 1, 1, 1, ConsoleColor.Black);
- }
- }
- }
///LetterManager类实现
- using System;
- using System.Collections.Generic;
- using CGraphics;
- namespace Typing
- {
- internal sealed class LetterManager
- {
- private List<Letter> m_letters;
- /// <summary>
- /// 下落字母的个数
- /// </summary>
- private Int32 m_fallNum;
- private Random m_random;
- private Int32 m_fallRate;
- public LetterManager(Int32 num, Int32 rate)
- {
- this.m_random = new Random();
- this.m_fallNum = num;
- this.m_fallRate = rate;
- this.m_letters = new List<Letter>();
- for (Int32 i = 0; i < m_fallNum; i++)
- {
- Letter letter = new Letter();
- letter.newLetter();
- this.m_letters.Add(letter);
- }
- }
- public List<Letter> getLetters()
- {
- return this.m_letters;
- }
- public Int32 getFallNum()
- {
- return this.m_fallNum;
- }
- public Int32 getFallRate()
- {
- return this.m_fallRate;
- }
- public void setFallRate(Int32 rate)
- {
- if (rate < 0)
- {
- this.m_fallRate = 1;
- return;
- }
- this.m_fallRate = rate;
- }
- public void addFallNum(Int32 num)
- {
- if (num <= 0)
- {
- return;
- }
- this.m_fallNum += num;
- for (Int32 i = 0; i < num; i++)
- {
- Letter letter = new Letter();
- letter.newLetter();
- this.m_letters.Add(letter);
- }
- }
- public void draw(CDraw draw)
- {
- for (Int32 i = 0; i < m_letters.Count; i++)
- {
- m_letters[i].draw(draw);
- }
- }
- }
- }
///TypingGame类实现
- using System;
- using System.Collections.Generic;
- using CEngine;
- using CGraphics;
- namespace Typing
- {
- public sealed class TypingGame : CGame
- {
- private LetterManager m_letBuilder;
- /// <summary>
- /// 打字正确个数
- /// </summary>
- private float m_rightCount;
- /// <summary>
- /// 打字个数
- /// </summary>
- private float m_typingCount;
- private CDraw m_draw;
- /// <summary>
- /// 倒计时
- /// </summary>
- private Int32 m_countDown;
- private Int32 m_lastTime;
- /// <summary>
- /// 下落速度控制
- /// </summary>
- private Int32 m_fallTime;
- /// <summary>
- /// 是否在打字
- /// </summary>
- private Boolean m_isType;
- private Random m_random;
- protected override void gameInit()
- {
- setTitle("控制台游戏之——键盘熟练工v1.0");
- m_letBuilder = new LetterManager(20, 2);
- setCursorVisible(false);
- setUpdateRate(40);
- m_rightCount = 0f;
- m_typingCount = 0f;
- m_countDown = 200;
- m_fallTime = 10;
- m_isType = false;
- m_random = new Random();
- m_draw = base.getDraw();
- m_draw.setDrawSymbol(CSymbol.RECT_SOLID);
- m_draw.drawRect(0, 0, 31, 25, ConsoleColor.White);
- m_draw.setDrawSymbol(CSymbol.DEFAULT);
- m_draw.fillRect(1, 0, 29, 1, ConsoleColor.Black);
- m_draw.setDrawSymbol(CSymbol.RHOMB_SOLID);
- m_draw.drawRect(31, 0, 9, 13, ConsoleColor.DarkYellow);
- m_draw.setDrawSymbol(CSymbol.RHOMB_SOLID);
- m_draw.drawRect(31, 12, 9, 13, ConsoleColor.DarkYellow);
- m_draw.drawText("倒计时:", 65, 2, ConsoleColor.Red);
- m_draw.drawText("正确率:", 65, 4, ConsoleColor.Green);
- m_draw.drawText("击键数:", 65, 6, ConsoleColor.Green);
- m_draw.drawText("FPS:", 65, 8, ConsoleColor.Green);
- m_draw.drawText("Rate:", 65, 10, ConsoleColor.Green);
- m_draw.drawText("操作:键盘A--Z键,根据下落的字母打击键盘对应的键位,正确率体现你的键盘操作熟悉程度。", new CRect(33, 14, 5, 10), ConsoleColor.DarkGreen);
- }
- protected override void gameDraw(CGraphics.CDraw draw)
- {
- m_letBuilder.draw(draw);
- draw.setBackcolor(ConsoleColor.Black);
- draw.drawText(m_countDown.ToString("000"), 73, 2, ConsoleColor.Red);
- if (m_typingCount != 0)
- {
- draw.drawText(((m_rightCount / m_typingCount) * 100).ToString("000") + "%", 73, 4, ConsoleColor.Red);
- }
- else
- {
- draw.drawText("0%", 73, 4, ConsoleColor.Red);
- }
- draw.drawText(m_typingCount.ToString("000"), 73, 6, ConsoleColor.Red);
- draw.drawText(getFPS().ToString(), 73, 8, ConsoleColor.Blue);
- draw.drawText(getUpdateRate().ToString(), 73, 10, ConsoleColor.Blue);
- }
- protected override void gameLoop()
- {
- if (m_fallTime == 0)
- {
- List<Letter> letters = m_letBuilder.getLetters();
- for (Int32 i = 0; i < letters.Count; i++)
- {
- //每个字母按几率下落
- if (m_random.Next(0, m_letBuilder.getFallNum() * m_letBuilder.getFallRate()) == i)
- {
- letters[i].setAlive(true);
- }
- //字母下落
- if (letters[i].getAlive())
- {
- letters[i].setPosition(letters[i].getPosition().getX(), letters[i].getPosition().getY() + 1);
- }
- //字母下落到地面
- if (letters[i].getPosition().getY() >= getClientRect().getHeight()-1)
- {
- letters[i].newLetter();
- m_typingCount++;
- }
- }
- m_fallTime = 5;
- }
- m_fallTime--;
- if (Environment.TickCount - m_lastTime > 1000)
- {
- m_lastTime = Environment.TickCount;
- m_countDown--;
- if (m_countDown == 0)
- {
- setGameOver(true);
- }
- }
- }
- protected override void gameExit()
- {
- m_letBuilder = null;
- base.getDraw().clear(ConsoleColor.Black);
- base.getDraw().drawText("Game Over!", 25, 10, ConsoleColor.Red);
- base.getDraw().drawText("Copyright (c) D-Zone Studio", 40, 10, ConsoleColor.White);
- Console.ReadLine();
- }
- protected override void gameKeyDown(CKeyboardEventArgs e)
- {
- if (!m_isType)
- {
- List<Letter> letters = m_letBuilder.getLetters();
- for (Int32 i = 0; i < letters.Count; i++)
- {
- if (letters[i].getAlive())
- {
- //是否打对字母
- if (letters[i].getChar().ToString() == e.getKey().ToString())
- {
- base.update(new CRect(letters[i].getPosition().getX(),letters[i].getPosition().getY(),1,1));
- letters[i].newLetter();
- m_rightCount++;
- break;
- }
- }
- }
- m_typingCount++;
- if (e.getKey() == CKeys.Escape)
- {
- setGameOver(true);
- }
- m_isType = true;
- }
- }
- protected override void gameKeyUp(CKeyboardEventArgs e)
- {
- m_isType = false;
- }
- }
- }
最后我们来欣赏下我们的劳动成果:
实话说,这个游戏DEMO实现得比较仓促,代码写得比较凌乱,但都是些简单的逻辑,相信大家都能看得明白。