如何在自动滚动的游戏中创建关卡?

时间:2012-01-08 08:12:29

标签: game-engine

我正在制作2D shmup,其想法是关卡会自动连续滚动,你的角色可以在屏幕上移动。

现在,我无法弄清楚如何实现这一点,谷歌也没有任何帮助。现在我有一个滚动的背景(背景位置只是每帧减少),玩家可以在窗口中自由移动,但我如何在关卡中创建对象?我是否只是使用计时器来触发对象和敌人,或者有没有办法根据背景的位置/宽度来做(我更喜欢第二种方法......但我不知道如何做到这一点) ?

由于这是一个普遍的问题,并且与我所知的任何代码完全无关,据我所知,我认为我不需要包含任何代码......但是我如果需要,我很乐意提供它的任何部分。

2 个答案:

答案 0 :(得分:2)

我建议:

  • 使用物理触发器
  • 使用定时事件列表

物理触发器

只需在您的关卡上放置一个方框即可。当它部分或完全滚动到屏幕上时(无论哪个更有意义 - 可能在不同的情况下都使用它们?),你会触发与该触发器相关的事件。

这在级别编辑器中支持会更简单,因为物理性质本质上很容易可视化。

定时事件

您基本上在关卡的开头创建一个计时器对象,以及一个有序的事件队列。在游戏更新循环中,查看队列的头部。如果队列头部的项目的触发时间小于当前经过的时间,则将该项目从队列中弹出并触发事件。

定时事件通常会更有用,因为它还支持非滚动级别或非滚动部分的级别。

两者的组合

您还可以进行某些组合,以获得两种风格的优势:更轻松的可视化/关卡编辑,支持非滚动部分或基于时间的事件。

每个物理触发器都有自己的脚本队列。触发器被触发时,启动计时器并创建事件队列。该计时器和队列被添加到当前运行的计时器和队列列表中。

在更新功能中,检查列表中的所有项目,并按照与上面的定时事件队列相同的方式触发事件。清空队列后,将其从计时器/队列列表中删除。

如何检测触发器是否在屏幕上

您应首先实现滚动。

您可以滚动一个,计算与您的像素/世界坐标系中屏幕所在位置相匹配的矩形。这将为您提供屏幕的“边界框”。

从这里开始,在事件触发器的“边界框”和屏幕之间进行交叉测试。

这是一个测试,看看两个矩形之间是否存在任何重叠。它不是特定于订单的:

rect1.left < rect2.right && rect1.right > rect2.left
    && rect1.top < rect2.bottom && rect1.bottom > rect2.top

如果rects完全触及,它将返回true。

这是一项测试,以确保rect1 包含 rect2。订单很重要:

rect1.left <= rect2.left && rect1.right >= rect2.right
    && rect1.top <= rect2.top && rect1.bottom >= rect2.bottom

如果rect2完全包含rect1(它完全在屏幕上),它将返回true。

如何实现简单的计时器

只需获得某种时钟值(可能是SDL_GetTicks),并存储该值。

要查看自该计时器启动以来已经过了多长时间,请再次调用该函数并减去。将值与<进行比较,以查看差异是否大于目标时间。

答案 1 :(得分:0)

不幸的是,这是你应该使用指针的地方。有点像:

vector<BadGuy*> Listofbaddies;

//Place enemy just off screen
newYposition = SCREEN_HEIGHT + 20;

//an infinite (almost) amount of badguys can be created with this code:
Listofbaddies.push_back(new Badguy(newXposition,
                                   newYposition,
                                   EnemyType,
                                   blahblah);

这意味着badguy需要一个构造函数,如:

Badguy::Badguy(float newX, float newY, string Type, whateverelseyouwant){

actualSpritePartOfBadguyClass.setPosition(newX, newY);
}

这有意义吗?如果你问我,我会详细说明:D 我正在制作一款使用类似东西的游戏:)