游戏屏幕

赛车游戏中有很多不同的游戏屏幕,这些都是由RacingGame类中的gameScreens堆栈管理的。本节介绍游戏中使用的大部分屏幕和对应的功能。大多数游戏屏幕相当简单,但其他的有点复杂并实现了一个单元测试,通过单元测试能更好地了解这个类。例如,Credits屏幕是相当简单的,它只显示一个背景纹理,但主菜单很复杂并具有所有能进入另一个屏幕的按钮。Options屏幕介绍了许多新的控制选项,这些都要进行测试,这个类里有一个单元测试能帮你完成这个过程。

所有的游戏屏幕类都继承于IgameScreen接口(见图14-6),您也许还记得在第8章的Rocket Commander中也使用过。几乎没有改变,但更简单了。您现在只有一个叫做Render的方法,它没有参数并返回一个布尔值。该代码和你在XNA Shooter中使用的几乎一样。如果Render方法返回true意味着您可以返回到以前的游戏屏幕,一旦推出最后一个游戏屏幕则游戏推出。通常游戏屏幕返回false,因为玩家再次进入游戏屏幕后不会立即退出。


图 14-6

由于这个简单的接口,所以所有的游戏屏幕的类视图几乎是一样的,它们都只有一个Render方法。有些类还会有一些私有的辅助方法,但它们大多是非常简单的。一些更复杂的游戏屏幕还有单元测试用以测试是否所有内容和功能都能正确实行。处理整个游戏的GameScreen类是复杂的。不像XNA Shooeter或Rocket Commander,所有游戏代码的的处理和渲染是在Landscape和model类中的。游戏逻辑在Player类中被处理,这个有点复杂,但你已经在上一章学习了所有的CarPhysics类的基本物理知识和ChaseCamera类。

看看图14-7了解一下游戏屏幕的基本概况。最复杂的类显然是Mission类,它处理游戏过程和游戏逻辑。它不包含所有的游戏代码,有些是在Player类和RacingGame类中被处理的。


图 14-7

启动屏幕

启动屏幕(见图14-8)是较容易的一个类,它只是等着玩家按下手柄上的Start。如果没有手柄,Space或Esc键或鼠标左键也可让玩家继续。这个类唯一令人感兴趣的地方就是让“Press Start to continue”文字闪烁的代码。


图 14-8

/// <summary>
/// Render splash screen
/// </summary>
public bool Render()
{// This starts both menu and in game post screen shader!BaseGame.UI.PostScreenMenuShader.Start();// Render background and black barBaseGame.UI.RenderMenuBackground();BaseGame.UI.RenderBlackBar(352, 61);// Show Press Start to continue.if ((int)(BaseGame.TotalTime / 0.375f) % 3 != 0)BaseGame.UI.Logos.RenderOnScreen(BaseGame.CalcRectangleCenteredWithGivenHeight(512, 352 + 61 / 2, 26, UIRenderer.PressStartGfxRect),UIRenderer.PressStartGfxRect);// Show logosBaseGame.UI.RenderLogos();// Clicking or pressing start will go to the menureturn Input.MouseLeftButtonJustPressed ||Input.KeyboardSpaceJustPressed ||Input.KeyboardEscapeJustPressed ||Input.GamePadStartPressed;
} // Render()

RenderMenuBackground方法有点复杂。它用来显示菜单背景,即显示出汽车通过一条赛道。汽车是由计算机控制的而相机只是跟随它。代码不是很复杂:

// [From RenderMenuTrackBackground(), which is called by
// RenderMenuBackground(), both located in the UIRenderer class]// [Some code to calculate carPos, carMatrix, etc.]// Put camera behind car
RacingGame.Player.SetCameraPosition(carPos + carMatrix.Forward * 9 - carMatrix.Up * 2.3f);// For rendering rotate car to stay correctly on the road
carMatrix =Matrix.CreateRotationX(MathHelper.Pi / 2.0f) *Matrix.CreateRotationZ(MathHelper.Pi) *carMatrix;RacingGame.Landscape.Render();
RacingGame.CarModel.RenderCar(randomCarNumber, randomCarColor, carMatrix);

借助于Landscape类的Render方法和Model类的RenderCar方法您不必担心渲染场景、赛道或其他东西。相机矩阵可以确保你在正确的位置上观看,而赛车通过汽车矩阵在赛道上行驶。.

所有其他游戏屏幕菜单也使用RenderMenuBackground方法显示屏幕背景,但在一些游戏屏幕上不太明显,因为你把一个较暗的纹理放在前面(例如,在Credits屏幕上很难看到背景)。这只是一个背景效果,当你正式开始玩游戏时你可以看到更多的屏幕。

主菜单

主菜单(见图14-9)比其他菜单屏幕复杂点,但即使这样这个类也只有约250行代码。除了启动屏幕,其他屏幕都是从这里开始的。最重要的选项是开始游戏和观看highscores (头两个按钮)。


图 14-9

这个类最酷的功能是菜单按钮的动画。每个按钮获得一个介于0和1之间的浮点值,其中0代表按钮尺寸的最小可能值而1代表最大。当鼠标悬浮或用手柄、键盘选择按钮时,它将慢慢变大直到达到1.0。当你离开按钮,它又缓慢变小。

第一个按钮初始设为1,其他按钮设为最小尺寸(0)。

/// <summary>
/// Current button sizes for scaling up/down smooth effect.
/// </summary>
float[] currentButtonSizes =new float[NumberOfButtons] { 1, 0, 0, 0, 0, 0 };

然后在Rnnder方法中处理按钮选择和缩放。为了确保你会在同时悬浮在一个以上的按钮,这里为鼠标使用了一个辅助变量。如果不使用鼠标选取菜单按钮,这个变量将不会被使用。

// Little helper to keep track if mouse is actually over a button.
// Required because buttons are selected even when not hovering over
// them for GamePad support, but we still want the mouse only to
// be applied when we are actually over the button.
int mouseIsOverButton = -1;// [a little later in the code ...]
for (int num = 0; num < NumberOfButtons; num++)
{// Is this button currently selected?bool selected = num == selectedButton;// Increase size if selected, decrease otherwisecurrentButtonSizes[num] +=(selected ? 1 : -1) * BaseGame.MoveFactorPerSecond * 2;if (currentButtonSizes[num] < 0)currentButtonSizes[num] = 0;if (currentButtonSizes[num] > 1)currentButtonSizes[num] = 1;// Use this size to build rectRectangle thisRect =InterpolateRect(activeRect, inactiveRect, currentButtonSizes[num]);Rectangle renderRect = new Rectangle(xPos, yPos - (thisRect.Height - inactiveRect.Height) / 2,thisRect.Width, thisRect.Height);BaseGame.UI.Buttons.RenderOnScreen(renderRect, ButtonRects[num],// Make button gray if not selectedselected ? Color.White : new Color(192, 192, 192, 192));// Add border effect if selectedif (selected)BaseGame.UI.Buttons.RenderOnScreen(renderRect,UIRenderer.MenuButtonSelectionGfxRect);// Also check if the user hovers with the mouse over this buttonif (Input.MouseInBox(renderRect))mouseIsOverButton = num;// [etc.]
} // for (num)if (mouseIsOverButton >= 0)selectedButton = mouseIsOverButton;
Game Screen

GameScreen类(见图14-10)是最重要的游戏屏幕,因为它处理整个游戏逻辑。游戏变量不储存在这个类,但所有的重要组成部分(场景,赛道,汽车,对象,HUD等)从这里被渲染和调用。


图 14-10

大多数玩家变量都存储在Player类,所有的输入和物理在Player的基类中(CarPhysics和ChaseCamera)处理。Player类还使用了所有的游戏变量比赛。大多数变量显示在用户界面中,比如在HUD上的目前的游戏时间,它们在Player类的HandleGameLogic方法中被更新。

所有Render方法,包括HUD,都在UIRenderer辅助类中处理,其余的在Landscape类和model类中处理和渲染,阴影映射也在那里进行。所有的渲染和游戏处理是从这里调用,所以这个类为您提供了游戏中发生了什么的一个很好的概括。如果你编写一个改编版本,那么从这开始修改代码。在这或调用方法中注释掉代码,能很快地看到游戏的哪一部分受到了影响。

Render方法的第一部分处理所有的阴影映射,这不是很复杂,因为大多数已在Landscape类中被处理了。你只需将数据提供给阴影映射类,这个类渲染所有阴影映射,这些阴影映射能直接被使用。

/// <summary>
/// Render game screen. Called each frame.
/// </summary>
public bool Render()
{
if (BaseGame.AllowShadowMapping)
{// Generate shadowsShaderEffect.shadowMapping.GenerateShadows(delegate{RacingGame.Landscape.GenerateShadow();RacingGame.CarModel.GenerateShadow(RacingGame.Player.CarRenderMatrix);});// Render shadowsShaderEffect.shadowMapping.RenderShadows(delegate{RacingGame.Landscape.UseShadow();RacingGame.CarModel.UseShadow(RacingGame.Player.CarRenderMatrix);});
} // if (BaseGame.AllowShadowMapping)

然后开始post-screen glow shader并渲染所有的3D内容。这包括天空盒,带有赛道的场景和所有三维模型,最后是汽车。

// This starts both menu and in game post screen shader!
BaseGame.UI.PostScreenGlowShader.Start();// Render background sky and lensflare.
BaseGame.UI.RenderGameBackground();// Render landscape with track and all objects
RacingGame.Landscape.Render();// Render car with matrix we got from CarPhysics
RacingGame.CarModel.RenderCar(RacingGame.currentCarNumber, RacingGame.CarColor,RacingGame.Player.CarRenderMatrix);// And flush all models to be rendered
BaseGame.MeshRenderManager.Render();

在MeshRenderManager渲染所有的三维模型后您可以添加阴影映射效果。这里的调用顺序是重要的,因为如果在显示阴影前还没有渲染三维模型,阴影将不正确或不工作。

// Show shadows we calculated above
if (BaseGame.AllowShadowMapping)
{ShaderEffect.shadowMapping.ShowShadows();
} // if (BaseGame.AllowShadowMapping)// Apply post screen shader here before doing the UI
BaseGame.UI.PostScreenGlowShader.Show();

代码的最后是游戏的用户界面,如果你想去除或改变HUD,在这里做这件事。

// Play motor sound
Sound.UpdateGearSound(RacingGame.Player.Speed,RacingGame.Player.Acceleration);// Show on screen UI for the game.
BaseGame.UI.RenderGameUI((int)RacingGame.Player.GameTimeMiliseconds,// Best time and current lap(int)RacingGame.Player.BestTimeMs,RacingGame.Player.CurrentLap+1,RacingGame.Player.Speed * CarPhysics.MeterPerSecToMph,// Gear logic with sound (could be improved ^^)1+(int)(5*RacingGame.Player.Speed/CarPhysics.MaxSpeed),// Motormeter0.5f*RacingGame.Player.Speed/CarPhysics.MaxSpeed +// This could be improved0.5f*RacingGame.Player.Acceleration,RacingGame.Landscape.CurrentTrackName,Highscore.GetTop5Highscores());if (Input.KeyboardEscapeJustPressed ||Input.GamePadBackJustPressed)
{// Stop motor soundSound.StopGearSound();// Play menu music againSound.Play(Sound.Sounds.MenuMusic);// Return to menureturn true;
} // if (Input.KeyboardEscapeJustPressed)return false;
} // Render()
Highscores

Highscores屏幕(见图14-11)非常相似与Rocket Commander的,但所有在线highscores被移除,因为没有实现网络代码或Web服务。原因仍是XNA缺乏网络支持,但在PC版本中仍有可能实现。


图 14-11

在Highscores类中有几个辅助方法,例如,帮助您确定当前在游戏中的排名,但大多数方法已经这本书的前面几个游戏中用到过了。

下面的代码是用来显示排行榜前10名的玩家。你会发现,借助于UIRenderer类中的辅助方法代码是很简单的。如果您只想测试Highscores游戏屏幕,请使用类内部的单元测试,这是用来定位所有的用户界面元素的,此游戏的其他屏幕也以同样的方式做这件事。我也在Visual Studio 2005使用了TestDriven.NET,它能通过热键重新运行测试。这样我可以测试代码,按下热键,说:“哦,不,”,按下Escape,并修复代码,直到类工作正常。大多数的UI代码都是通过这种方式进行测试的。

// Go through all highscores
for (int num = 0; num < NumOfHighscores; num++)
{// Show player in white if mouse is over line or else use gray colorRectangle lineRect = new Rectangle(0, yPos, BaseGame.Width, lineHeight);Color col = Input.MouseInBox(lineRect) ?Color.White : new Color(200, 200, 200);// Fill in text for this lineBaseGame.UI.WriteText(xPos1, yPos, (1 + num) + ".", col);BaseGame.UI.WriteText(xPos2, yPos,highscores[selectedLevel, num].name, col);BaseGame.UI.WriteGameTime(xPos3, yPos,highscores[selectedLevel, num].timeMs, Color.Yellow);yPos += lineHeight;
} // for (num)

剩下的其他游戏屏幕类是Option,Help和Credit。它们和highscores类非常相似,并不令人兴奋。Option有一些不错的UI功能,可以让你在Input类的帮助下输入文字,选取其中一个或多个滑块并拖动它们。使用Option类的单元测试更多地了解这些功能。Help和Credit类只是在屏幕上显示一个纹理,非常类似于你先前看到的SplashScreen类。

最后,点击退出按钮可以退出游戏,因为主菜单关闭后将不会有其他游戏屏幕了。而所有其他游戏屏幕总是返回到主菜单(包括SplashScreen类)。

转载于:https://www.cnblogs.com/AlexCheng/archive/2010/10/17/2120185.html

调整和改编赛车游戏——游戏屏幕相关推荐

  1. 调整和改编赛车游戏——更多的想法

    更多的想法 游戏现在已经运行得很好了,如果你已通过最终的测试它就可以发布了.但即使您可能还没有全部完成,你也可能要尝试更多的想法或思考未来的扩展.我发现自己经常重用现有的引擎来测试新的游戏构思.使用您 ...

  2. 【源代码】Python制作的赛车小游戏,逆行飙车

    python制作的赛车小游戏,逆行飙车,通过键盘方向键控制 程序运行截图 源代码 import pygame, sys, time, random# pygame 初始化 pygame.init() ...

  3. Unity中2D游戏多分辨率屏幕适配方案

    一:什么是像素? 像素是由很多个小方格组成,每一个小方格上都存储了位置信息和色彩信息.像素是图像的最小单位 图像分为两类:位图和矢量图 --位图(点阵图):由多个像素组成,当放大时被分为多个色块,而且 ...

  4. Python制作的赛车小游戏源代码,逆行飙车

    python制作的赛车小游戏,逆行飙车,通过键盘方向键控制 程序运行截图: 源代码 import pygame, sys, time, random# pygame 初始化 pygame.init() ...

  5. 【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(二)物理刚体关节

    [Cocos Creator游戏开发教程]仿微信趣味画赛车小游戏(一)前言,界面UI 项目地址已放到 github 上,需要的小伙伴可自行下载. 这节我们讲一下车子的物理刚体关节. 我在项目中添加了一 ...

  6. 解决玩游戏时屏幕卡住的现象

    笔者朋友有一台计算机,具体配置为奔腾 4 3.0E CPU.512M内存.160GSATA硬盘,该计算机使用的显示卡为祺祥极风6600的AGP类型的显卡.最近使用这台计算机玩一些大型游戏程序时,常常会 ...

  7. [Unity] 制作游戏 赛车小游戏

    模拟赛车小游戏 效果展示 做一款模拟赛车的小游戏demo,方向键控制.有刹车.重玩,还有漂移和查看车型的功能 可以看到,还有翻车的效果哈哈哈!有兴趣的小伙伴来看看吧! 资源准备 从网上下载赛车模型和桥 ...

  8. 加菲猫卡丁车:激情竞速 Mac(卡通赛车竞速游戏)原生版

    Garfield Kart Furious Racing Mac是一款以加菲猫为主题的卡通赛车竞速游戏,玩家可以在游戏加菲猫卡丁车中文版中操控加菲猫,小狗阿德.奈梅尔.乔恩等动画角色在赛场上比赛.加菲 ...

  9. 【Cocos Creator游戏开发教程】仿微信趣味画赛车小游戏(三)代码实现

    [Cocos Creator游戏开发教程]仿微信趣味画赛车小游戏(一)前言,界面UI [Cocos Creator游戏开发教程]仿微信趣味画赛车小游戏(二)物理刚体关节 项目地址已放到 github ...

最新文章

  1. centos下axel安装与使用
  2. HTML5 - Websocket
  3. R语言使用party包中的ctree函数构建条件推理决策树(Conditional inference trees)、使用plot函数可视化训练好的条件推理决策树、条件推理决策树的叶子节点的阴影区域表
  4. 阿里云前端周刊 - 第 39 期
  5. 提高电路板EMC能力PCB设计和布线方法
  6. 邻接矩阵和邻接表的相互转化
  7. vs2010 在svn上传东西的时候 出现一个错误 An internal occurred 值不在预期范围内 要如何解决呢?...
  8. 海底捞:今年年底前将关停约300家经营未达预期门店
  9. STM32单片机一个定时器输出不同频率PWM波
  10. BZOJ 1295: [SCOI2009]最长距离 spfa
  11. maven中GroupID 和ArtifactID怎么写
  12. [c++]在C++中定义常量的两种方法的比较
  13. MySQL命令行登录数据库
  14. 概率逗号分号_概率P中有多个逗号表示什么意思
  15. JAVA基础学习(二)
  16. html+text+shadow语法,text-shadow属性怎么用
  17. GAN 的内在漏洞,只看眼睛就能找出虚拟人脸?
  18. 零基础怎样学IT难吗?新手如何快速入门?
  19. 理解accuracy/precision_score、micro/macro
  20. pip安装模块时换源下载

热门文章

  1. java线程提交_从Java线程到线程池
  2. java 快速构建ssm项目_SSM快速搭建
  3. open表和closed表_excel工作表合并,多文件数据一键合成
  4. vue 子父组件周期顺序_父组件和子组件生命周期钩子执行顺序是什么?
  5. Metaspliot 控制终端利用Samba漏洞渗透
  6. java实验文法报告_西安邮电大学编译原理LL文法分析器实验(java).doc
  7. 课时27.base(掌握)
  8. 对 Vue 的理解(一)
  9. js 分页插件(jQuery)
  10. 网页中二维码识别规则