write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
讨论新闻组及文件
其实在上一节,游戏已经基本成型了,但是还不能算是完整的游戏,本篇将需要完善的部分完成吧。
游戏加个边框
这个实在不需要我额外讲方法了,按原来的办法加上四周的边框即可。不过这里讲几个个人总结的技巧,边框需不需要显示呢?需要显示的话,那没有话说,直接创造一个边框就可以了,不需要显示呢?我想出了两个办法,其一,将边框创造在显示范围以外,那么自然是看不见了。其二,创建完全透明的图,那么你就可以将边框放置在任何你想要加碰撞阻挡,却不希望玩家看到的位置了。其三,不透明的图其实也行,只需要放置在Z轴超出视景体即可(大于远剪裁面,小于等于近剪裁面),由于box2D是2D的物理引擎,会忽略Z轴,同样的,只要X,Y轴对了,你还是能够获取到你想要的碰撞效果。
这里由于懒得做资源了,直接使用Orx作者的资源和配置,所以使用第一种方法。
首先,用作者的wall.png创造四周的墙壁,为了先看到直观的看到碰撞效果,同时也为了大概确认位置正确,我们首先将墙壁置为可见。
配置如下:
; Wall
[WallTemplate]
Graphic =
WallGraphic
Body =
WallBody
BlendMode =
alpha
[WallGraphic]
Texture =
data/wall.png
Pivot =
center
[Walls]
ChildList =
Wall1 # Wall2 # Wall3 # Wall4
[Wall1@WallTemplate]
Position =
(0.0, 250, 0.0)
Rotation =
90.0
[Wall2@WallTemplate]
Position =
(-170, 0.0, 0.0)
[Wall3@WallTemplate]
Position =
(0.0, -250, 0.0)
Rotation =
90.0
[Wall4@WallTemplate]
Position =
(170, 0.0, 0.0)
[WallBody]
PartList =
WallBox
Dynamic =
false
[WallBox]
Type =
box
Friction =
1.0
Restitution =
0.0
SelfFlags =
0x0001
CheckMask =
0x0001
Solid =
true
我新建了一个名为wall.ini的配置文件,此时在原来的game.ini中添加下面这条语句表示包含。
@wall.ini@
其他的配置的含义在上一节中已经提到过,这里不重复了。
然后,在初始化的时候新添加一条代码创造墙壁。
if (orxObject_CreateFromConfig("Walls") == NULL) {
result = orxSTATUS_FAILURE;
}
看到这里,提一下Orx作者iarwain推荐的方法,iarwain推荐大量的不需要直接获取指针的对象可以通过一个类似于scene的配置端来配置,然后通过ChildList字段串起来,由于一个ChildList的列表长度是255个,(已经够多了)假如还不够的话,任意一个ChildList指定的对象还可以是仅包含ChildList的字段。。。。。如此串起来,无穷尽也。。。。以此构建整个场景。。。。。好处是可以动态添加新的东西,完全不用像我一样添加代码。
然后,就可以看到正常的碰撞效果了。而且也可以看到墙壁存在。要将难看的墙壁消去,只需要修改配置将墙壁移到显示范围外即可(记得计算墙壁本身的宽度)

此例中部分配置实际的为如下内容即可:(将墙都往屏幕外移动10像素)
[Wall1@WallTemplate]
Position =
(0.0, 260, 0.0)
Rotation =
90.0
[Wall2@WallTemplate]
Position =
(-180, 0.0, 0.0)
[Wall3@WallTemplate]
Position =
(0.0, -260, 0.0)
Rotation =
90.0
[Wall4@WallTemplate]
Position =
(180, 0.0, 0.0)
响应输入
有人将游戏称为第9艺术,并且,游戏与电影的区别就在于更多的交互,这里,我们来谈谈交互^^当然,那就是响应玩家的输入,并且做出反应罗。这里是用Win32平台来做例子的,所以,就说键盘输入吧。
首先,为了不在Run函数中去响应键盘输入,我添加一个新的自己的Update函数,需要是用一个计时器,相关的知识可以参考官方的中文WIKI
。
需要用下面两句注册一个Update的回调函数,这里创建的是20HZ的clock。
orxCLOCK *pstClock = orxClock_Create(orx2F(0.05f
), orxCLOCK_TYPE_USER);
orxClock_Register(pstClock, GameApp::Update, NULL
, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);
然后就可以在Update里面处理我们的的输入了。
首先,配置部分,很简单。
[Input]
SetList =
Input
KEY_LEFT =
GoLeft
KEY_RIGHT =
GoRight
主要就是配置Input配置段,这里的SetList一般情况下可以是其他配置段的名字,并且可以是一个list,这里为求简单,我指向了自身(配置简单化大法之一),这样就可以省下一个section。这里的配置表示按左方向键表示GoLeft的动作,按右方向键表示GoRight的动作。
我们在代码里面看GoLeft和GoRight怎么用的:
void
GameApp::Update(const
orxCLOCK_INFO *_clock_info, void
*_context)
{
#define MOVE_SPEED
10
if
( orxInput_IsActive("GoLeft"
) ) {
orxVECTOR pos;
orxObject_GetPosition(gPaddle, &pos);
pos.fX -= MOVE_SPEED;
orxObject_SetPosition(gPaddle, &pos);
} if
(orxInput_IsActive("GoRight"
)) {
orxVECTOR pos;
orxObject_GetPosition(gPaddle, &pos);
pos.fX += MOVE_SPEED;
orxObject_SetPosition(gPaddle, &pos);
}
}
这里的gPaddle就是全局的paddle指针。然后,此时的游戏已经可以玩了。按左右方向键移动paddle即可。

这里再贴一下新的完整代码,有部分修改,还有一些改进前一节教程的内容
1
2
#include
"orx.h"
3
4
#include
5
#include
6
using
namespace
std;
7
orxOBJECT* gPaddle;
8
class
GameApp
9
{
10
public
:
11
static
orxSTATUS orxFASTCALL EventHandler(const
orxEVENT *_pstEvent);
12
static
orxSTATUS orxFASTCALL Init();
13
static
void
orxFASTCALL Exit();
14
static
orxSTATUS orxFASTCALL Run();
15
static
void
orxFASTCALL Update(const
orxCLOCK_INFO *_clock_info, void
*_context);
16
17
GameApp() {};
18
~GameApp() {};
19
20
static
GameApp* Instance() {
21
static
GameApp instance;
22
return
&instance;
23
}
24
25
private
:
26
orxSTATUS InitGame();
27
};
28
29
#define BLOCK_TYPE
1
30
31
orxOBJECT *CreateText(orxSTRING _zTextSection)
32
{
33
orxConfig_PushSection(_zTextSection);
34
orxConfig_SetString("Graphic"
, _zTextSection);
35
orxConfig_SetString("Text"
, _zTextSection);
36
37
orxOBJECT *pstReturn = orxObject_CreateFromConfig(_zTextSection);
38
39
orxConfig_PopSection();
40
41
return
pstReturn;
42
}
43
44
// Init game function
45
orxSTATUS GameApp::InitGame()
46
{
47
orxSTATUS result = orxSTATUS_SUCCESS;
48
orxCLOCK *pstClock = orxClock_Create(orx2F(0.05f
), orxCLOCK_TYPE_USER);
49
orxClock_Register(pstClock, GameApp::Update, NULL
, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);
50
51
52
// Creates viewport
53
if
( orxViewport_CreateFromConfig("Viewport"
) == NULL
) {
54
result = orxSTATUS_FAILURE;
55
}
56
57
if
(orxObject_CreateFromConfig("Ball"
) == NULL
) {
58
result = orxSTATUS_FAILURE;
59
}
60
61
62
if
( (gPaddle = orxObject_CreateFromConfig("Paddle"
)) == NULL
) {
63
result = orxSTATUS_FAILURE;
64
}
65
66
if
(orxObject_CreateFromConfig("Blocks"
) == NULL
) {
67
result = orxSTATUS_FAILURE;
68
}
69
70
if
(orxObject_CreateFromConfig("Walls"
) == NULL
) {
71
result = orxSTATUS_FAILURE;
72
}
73
74
orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS, GameApp::EventHandler);
75
// Done!
76
return
result;
77
}
78
79
// Event handler
80
orxSTATUS orxFASTCALL GameApp::EventHandler(const
orxEVENT *_pstEvent)
81
{
82
orxSTATUS eResult = orxSTATUS_SUCCESS;
83
if
(_pstEvent->eType == orxEVENT_TYPE_PHYSICS) {
84
if
( _pstEvent->eID == orxPHYSICS_EVENT_CONTACT_REMOVE ) {
85
/*
Gets colliding objects
*/
86
orxOBJECT *object_recipient = orxOBJECT(_pstEvent->hRecipient);
87
orxOBJECT *object_sender = orxOBJECT(_pstEvent->hSender);
88
89
string recipient_name(orxObject_GetName(object_recipient));
90
string sender_name(orxObject_GetName(object_sender));
91
if
(sender_name.substr(0
, sender_name.length()-1
) == "Block"
) {
92
// 这样比直接删除要安全
93
orxObject_SetLifeTime(object_sender, orxFLOAT_0);
94
}
95
}
96
}
97
// Done!
98
return
orxSTATUS_SUCCESS;
99
}
100
101
void
GameApp::Update(const
orxCLOCK_INFO *_clock_info, void
*_context)
102
{
103
#define MOVE_SPEED
10
104
if
( orxInput_IsActive("GoLeft"
) ) {
105
orxVECTOR pos;
106
orxObject_GetPosition(gPaddle, &pos);
107
pos.fX -= MOVE_SPEED;
108
orxObject_SetPosition(gPaddle, &pos);
109
110
} if
(orxInput_IsActive("GoRight"
)) {
111
orxVECTOR pos;
112
orxObject_GetPosition(gPaddle, &pos);
113
pos.fX += MOVE_SPEED;
114
orxObject_SetPosition(gPaddle, &pos);
115
}
116
}
117
// Init function
118
orxSTATUS GameApp::Init()
119
{
120
orxSTATUS eResult;
121
orxINPUT_TYPE eType;
122
orxENUM eID;
123
124
/*
Gets input binding names
*/
125
orxInput_GetBinding("Quit"
, 0
, &eType, &eID);
126
const
orxSTRING zInputQuit = orxInput_GetBindingName(eType, eID);
127
128
// Logs
129
orxLOG("
n
- '
%s
' will exit from this tutorial"
130
"
n
* The legend under the logo is always displayed in the current language"
, zInputQuit );
131
132
orxLOG("Init() called!"
);
133
134
// Inits our stand alone game
135
eResult = GameApp::Instance()->InitGame();
136
137
// Done!
138
return
eResult;
139
}
140
141
// Exit function
142
void
GameApp::Exit()
143
{
144
145
// Logs
146
orxLOG("Exit() called!"
);
147
}
148
149
// Run function
150
orxSTATUS GameApp::Run()
151
{
152
orxSTATUS eResult = orxSTATUS_SUCCESS;
153
154
155
// Done!
156
return
eResult;
157
}
158
159
160
// Main program function
161
int
main(int
argc, char
**argv)
162
{
163
// Inits and runs orx using our self-defined functions
164
orx_Execute(argc, argv, GameApp::Init, GameApp::Run, GameApp::Exit);
165
166
// Done!
167
return
EXIT_SUCCESS
;
168
}
169
170
171
#ifdef __orxMSVC__
172
173
// Here's an example for a console-less program under windows with visual studio
174
int
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
175
{
176
// Inits and executes orx
177
orx_WinExecute(GameApp::Init, GameApp::Run, GameApp::Exit);
178
179
// Done!
180
return
EXIT_SUCCESS
;
181
}
182
183
#endif
// __orxMSVC__
一共183行。我并没有特意的精简代码,比如有两个可供切换的Main函数部分,有很多可以Init部分其实也都可以通过iarwain的方式缩减。
全部的源代码在:https://orx-sample.jtianling.googlecode.com/hg/
上,可以通过mercurial直接获取。
这里同样提供一个对比的参考。
《How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 1/2
》
《How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 2/2
》
点击链接下载源代码:Cocos2D and Box2D Breakout Game
原创文章作者保留版权 转载请注明原作者 并给出链接
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
分享到:
相关推荐
- 卓越商企服务的母公司卓越集团是一家在房地产开发领域具有较强实力的企业,其销售规模和市场排名均呈上升趋势,这将可能为卓越商企服务带来更多关联方项目。 - 关联交易收入占比低于同业平均水平,显示公司的...
八年级物理全册1.3站在巨人的肩膀上我国的四大发明素材新版沪科.doc
本项目“站在巨人肩膀上制作的异步非阻塞IM”是一个基于Java语言实现的高效通信平台,它巧妙地利用了现有的开源技术和工具,以解决大规模并发下的高性能通信问题。以下将详细阐述这个项目中的关键知识点。 首先,...
本教程资源"ios-站在巨人的肩膀上-scrollView联动.zip"可能包含了一个名为"XYSlideMenu"的示例项目,旨在帮助开发者理解并实现ScrollView的联动效果。 ScrollView联动的核心是通过监听ScrollView的滚动事件,将滚动...
《奔跑吧巨人》是一款基于Cocos Creator 3引擎开发的3D冒险闯关游戏,源码的公开为开发者提供了一次深入学习和理解3D游戏制作的宝贵机会。Cocos Creator 3作为Cocos系列的最新版本,不仅在2D游戏开发上表现出色,还...
UCloud基础云产品中心总监俞圆圆女士在她题为《站在巨人的肩膀上-构建公有云平台上的容器服务》的技术分享中,深入探讨了如何在公有云平台上有效地构建和优化容器服务。 俞圆圆女士拥有丰富的行业经验,曾在国际...
本项目“站在巨人肩膀上制作了异步非阻塞的IM”充分利用了Java的优势,构建了一个高效、灵活的多协议通讯解决方案。 首先,异步非阻塞编程模型是现代高性能网络应用的核心。传统的同步阻塞模型在处理高并发时容易...
《奔跑吧巨人》是一款基于Cocos游戏引擎开发的小游戏,其源码的公开为我们提供了一个深入了解小游戏开发的宝贵机会。Cocos是一个广泛应用于2D游戏开发的开源框架,以其高效、易用和跨平台的特性受到开发者们的青睐。...
描述中提到的内容是故事的一部分,讲述了巨人对孩子们的态度转变,以及花园在孩子们存在和不在时的两种截然不同的景象。这部分内容揭示了故事中的一个重要主题:分享与友谊带来的温暖和生命的活力。 故事中的标签...
绿洲APP产品分析报告:站在巨人肩膀上能否看得更远?.pdf
【金工专题报告】主要探讨了机构业绩增强的策略,特别是在金融工程的背景下,如何利用机构投资风格追随来提升投资回报。报告指出,传统的α策略通常以宽基指数作为基准进行指数增强,但这里提出了一种新的方法,即以...
站在巨人的肩膀上:分层设计在 Nervos 生态系统中的 layer 2区块链上的实际应用-SACC2021年中国系统架构师大会
资源描述让你站在HTML巨人的肩膀上,制作非常酷炫的HTML前端web幻灯片。通过使用资源描述,你可以轻松地添加各种动画效果,使你的网页更加生动有趣。无论是淡入淡出、滑动、旋转还是缩放,你都可以通过资源描述实现...
站在巨人的肩膀上,_迁移学习_Transfer_Learning
读完本书,受益匪浅,与大家共享!!! 让我们站在巨人的肩膀上。
本报告聚焦于保险行业的“御繁归简”系列,特别关注再保险领域,将其比喻为站在直保市场背后的巨人。随着保险行业向保障型业务转型,再保险的需求逐渐显现。报告指出,人身险销售模式从单一产品转向“1+N”组合,...
这篇报告的标题“小米集团,站在“巨人们”的肩膀上看世界-家用电器行业-20180507-国盛证券-59页”揭示了报告的主要内容,即小米集团在2018年5月7日时在家用电器行业的战略定位和发展情况。报告由国盛证券发布,通常...
【标题】中的“站在巨人的肩膀上的项目,感谢zhile大佬的Pandora-Next项目”表明这是一个基于他人开源项目进行开发或改进的项目。这里的“Pandora-Next”可能是一个由用户“zhile”创建的开源项目,它很可能在Python...
在C++编程中,错误处理是一项至关重要的任务,因为它们能帮助我们发现并修复程序中的问题,从而提高软件的质量和稳定性。...记住,每一次错误都是学习的机会,站在前人的经验上,我们可以走得更远。