Movement
译:运动
Lets get things moving! Movement in our case is going to be handled by our Entity class. Each loop we'll ask the entities in the game to move themself. To facilitate this we add a list of entities to the main game class. Each loop we'll cycle round this list asking each entity to move and then draw itself. In our game loop, that looks like this:
译:让游戏角色动起来!在我们的例子中,运动由实体类来处理。每次循环我们将要求实体们移动自己。为了方便实现,我们为游戏主窗口添加了一个实体列表。每次游戏循环重新开始我们将循环实体列表要求每一实体移动并绘制自己。在我们的游戏中,这样来实现实体的运动:
// cycle round asking each entity to move itself
循环实体列表要求每一实体移动自己。
for (int i=0;i<entities.size();i++) {
Entity entity = (Entity) entities.get(i);
entity.move(delta);
}
// cycle round drawing all the entities we have in the game
循环绘制游戏中所有的实体。
for (int i=0;i<entities.size();i++) {
Entity entity = (Entity) entities.get(i);
entity.draw(g);
}
Remember we calculated how long it'd been since we looped round. This can be used to work out how far an entity should move on the current loop. Right, now we know what Entity needs to be able to do, on to the implementation.
译:计算上次循环开始到本次循环的时长,它能够用来算出实体应该在当前循环中移动多远。好的,现在我们知道实体需要实现什么功能了。
The Entity class 实体类
The entity class will contain its currently location, its current movement and its visual representation. When an Entity is constructed these values will be defined. This includes retrieving the sprite from the store that should represent this entity. The location and movement associated with the entity will be definable and retriveable via get and set methods.
译:实体类将控制其在屏幕中的当前位置,当前的移动和外观。在实体构建时,这些值将会被定义。这包括从缓存中获取代表实体的精灵。实体的位置和运动可以通过set和get方法进行读取和设置。
/** The current x location of this entity 实体的当前位置 x 坐标*/
protected double x;
/** The current y location of this entity 实体的当前位置 y 坐标*/
protected double y;
/** The sprite that represents this entity 代表实体的精灵*/
protected Sprite sprite;
/** The current speed of this entity horizontally (pixels/sec) 实体水平方向上的当前速度(像素/秒)*/
protected double dx;
/** The current speed of this entity vertically (pixels/sec) 实体垂直方向上的当前速度(像素/秒)*/
protected double dy;
/**
* Construct a entity based on a sprite image and a location.
* 在精灵图片和坐标的基础上构造一个实体
*/
public Entity(String ref,int x,int y) {
this.sprite = SpriteStore.get().getSprite(ref);
this.x = x;
this.y = y;
}
Once these properties are defined we can cover the two methods that we require of Entity. The move() method looks like this:
译:一旦这些属性被定义,我们可以覆盖实现实体类要求实现的两个方法。move() 方法的实现如下:
public void move(long delta) {
// update the location of the entity based on move speeds 根据运动速度更新实体的坐标位置
x += (delta * dx) / 1000;
y += (delta * dy) / 1000;
}
Simple! We take how every much time has passed, multiply it by the movement in each direction and add this on to the location. The division by 1000 is to adjust for the fact that the movement value is specified in pixels per second, but the time is specified in milliseconds. Each loop all the entities will be moved in accordance with their currently movement values (velocities).
译:就是这么简单!我们用逝去时间(delta,以毫秒为单位)乘以在每个方向的运动速度(以像素/秒为单位),再除以1000是为了将运动速度的单位从“像素/秒”转换成“像素/毫秒”,计算结果累加到实体的坐标位置(计算结果与实体的坐标位置相加,再复制给实体坐标位置)。这样一来,每次循环,所有实体将被按照他们当前的移动速度值和逝去时间进行移动。
Next we need to be able to draw an Entity onto our accelerated graphics context. draw() is implemented like this:
译:接下来,我们需要能够将实体绘制到我们的加速图形上下文环境。draw()方法是这样实现的:
public void draw(Graphics g) {
sprite.draw(g,(int) x,(int) y);
}
Essentially, this just draws the sprite onto the supplied graphics context at its current location. So each loop, the entity moves and is then redrawn at the right location.
译:实际上,我们只是将精灵按照其坐标位置绘制到draw()方法参数提供的图像上下文中。因此,每一次循环实体都移动,然后在正确的位置重绘自己。
Now we've defined our basic entity we should create a few subclasses as placeholders for some more functionality we'll add later on. We simply need to create the 3 subclasses of Entity; ShipEntity, ShotEntity and AlienEntity. For now we won't bother adding anything extra but it normally pays to be aware and add these things up front.
译:现在我们已经定义了我们的基本实体,我们应该创造一些子类,作为占位符,以在将来添加更多的功能。 我们只需要建立三个实体子类:ShipEntity(玩家战船),ShotEntity(子弹实体)和AlienEntity(外星人实体)。
The final step is to create our entities and add them to the game world. If we add a utility method to central Game class called initEntities(). This will initialise a set of entities at the game start. The current implementation looks like this:
译:最后一步是创建我们的实体,并将它们加入到游戏的世界。我们将增加一个叫作initEntities()的方法到核心 Game 类,其将在游戏启动时,初始化一个实体的集合。当前的实现如下:
private void initEntities() {
// create the player ship and place it roughly in the center of the screen
//创建玩家飞船,并将其绘制在屏幕中间
ship = new ShipEntity(this,"sprites/ship.gif",370,550);
entities.add(ship);
// create a block of aliens (5 rows, by 12 aliens, spaced evenly)
//创建外星人方阵(5行,每行12个外星人,间隔军均匀)
alienCount = 0;
for (int row=0;row<5;row++) {
for (int x=0;x<12;x++) {
Entity alien = new AlienEntity(this,
"sprites/alien.gif",
100+(x*50),
(50)+row*30);
entities.add(alien);
alienCount++;
}
}
}
As you can see, the initialisation takes two steps. The first is to create the player's ship. We simply create a ShipEntity with the appropriate graphic and center it at the bottom of our canvas.
译:就像你看到的,初始化分为两步。第一步是创建玩家战船。我们简单地创建了一个 ShipEntity ,并将其绘制到游戏画布的底部中心位置。
The second step is to create all the aliens. We loop through creating a block of aliens. Again each alien is just the creation of the AlienEntity positioned at the right location. In addition we count how many aliens we've created so we can track whether the player has won the game.
译:第二步是创建所以的外星人。我们通过循环创建一个外星人方阵。每一个外星人只是一个放置在正确位置的AlienEntity 对象。 此外,我们还统计创建了多少外星人,以追踪玩家是否赢得了比赛。
Assuming the code to support moving and displaying the entities has been added to main game loop, running the game should now show the player's ship and a bunch of aliens.
译:假设代码支持移动和显示已被添加到游戏主循环的实体,现在运行游戏应显示玩家的船和一群外星人。
Now each type of Entity moves in its own way and with its own contraints. Lets look at each one.
译:现在,每个类型的实体以自己的方式运动,并有它们自己的约束。让我们看一下每一个实体的实现。
Ship Entity 战船实体
Since the ship will be controlled by the player (see a little lower down) we have very little to do here. However, we do want to prevent the ship moving off the sides of the screen so we add this bit of code to the move() method in ShipEntity:
译:由于战船将由玩家控制(后面我们可以看到)。在 ShipEntity 的 move() 中我们只有很少的事情可以做,就是防止战船移动时越过屏幕的两侧。因此,我们在 ShipEntity 的 move()方法中加入这段代码:
public void move(long delta) {
// if we're moving left and have reached the left hand side
// of the screen, don't move 如果战船正在向左移动,并且已经到达屏幕左边界,停止移动
if ((dx < 0) && (x < 10)) {
return;
}
// if we're moving right and have reached the right hand side
// of the screen, don't move 如果战船正在向右移动,并且已经到达屏幕右边界,停止移动
if ((dx > 0) && (x > 750)) {
return;
}
super.move(delta); //移动
}
What we essentially are saying here is that if we're moving left and we're about to move off the left hand side of the screen then don't allow the movement (i.e. return). In reverse if we're moving to the right and are about to move off the right hand side of the screen then don't allow the movement. Otherwise we just do the normal Entity movement routine.
译:我们基本上是在这里说的是,如果战船正在向左移动,并且将要移出屏幕左边界,则不允许移动(即retrun )。反之,如果战船正在向右移动,并且将要移出屏幕右边界,则不允许移动。否则,我们执行实体正常的运动逻辑。
Shot Entity 子弹实体
The shot entity is pretty simple, it just wants to run up the screen until it either hits an alien (see Collision later on) or runs off the top of the screen, at which point we'd like to remove it from the entity list (for details of the remove entity method check out the source).
译:子弹实体很简单,它只是想在屏幕上跑起来直到它击中外星人(见后面碰撞)或移出屏幕的顶部,这时,我们要从实体列表将其删除(有关删除实体的方法实现详情请参考源代码)。
To start the shot moving with initialise the vertical movement to a negative number based on the speed we'd like the shot to move. The movement method itself looks like this:
译:初始化子弹的移动速度为一个负数,其将从屏幕下方向上方做垂直运动。移动方法的实现看起来像这样:
public void move(long delta) {
// proceed with normal move 处理正常移动
super.move(delta);
// if we shot off the screen, remove ourselfs 如果移出屏幕,删除自己
if (y < -100) {
game.removeEntity(this);
}
}
Simply put, if the shot moves off the top of the screen, remove it.
译:简单地说,如果子弹移出屏幕上方,将其删除。
Alien Entity 外星人实体
Aliens are the most tricky part of our space invaders game. As they move around we need to notice when they hit the side of the screen and start them moving in the opposite direction. In conjuction each time they change direction we'd like them all to move down a step. Part of this will be covered in the movement routine and part in the game logic. Game logic is used in this case since we need to first detect that the aliens should change direction then change them all (rather than a localised change like the other entities)
译:外星人的实现是我们的太空入侵者游戏中最棘手的部分。在他们移动的过程中,我们需要检测到他们何时碰触到屏幕的边界,并让他们开始向相反的方向移动。每当外星人实体一起选择改变移动方向时,我们希望他们都向下移动一步。本部分的实现一部分由实体类的move() 方法,另一部分在实现游戏逻辑时实现(游戏主循环中)。在游戏逻辑的实现中,我们需要首先检测到的外星人应该改变移动方向,然后改变所有外星人的移动方向(而不是像其他实体的局部变化) 。
Hopefully, we now know what we want to do, so how? First we initialise the movement of the aliens to start them moving to the left based on the predefined speed. Next we put the detection of an alien hitting the side in the movement routine like this:
译:希望我们现在已经知道我们想要做什么了,那么又如何实现呢?首先,我们初始化外星人运动,让它们以预定义的速度开始向左移动。接下来我们像下面代码实现这样检测一个外星人在运动中是否碰触了边界:
public void move(long delta) {
// if we have reached the left hand side of the screen and
// are moving left then request a logic update 如果我们到达了屏幕左边界并且正在向左移动,请求游戏更新逻辑(让所有外星人向相反方向移动)
if ((dx < 0) && (x < 10)) {
game.updateLogic();
}
// and vice vesa, if we have reached the right hand side of
// the screen and are moving right, request a logic update 如果我们到达了屏幕右边界并且正在向右移动,请求游戏更新逻辑(让所有外星人向相反方向移动)
if ((dx > 0) && (x > 750)) {
game.updateLogic();
}
// proceed with normal move 处理正常移动
super.move(delta);
}
In the same way as in ShipEntity, we check whether the entity has hit the edge of the screen. However, in this case we notify the game that the game logic for all entities need to be run. We'll make this logic adapt the movement of the aliens but more on this later.
译:和 ShipEntity 的方法一样,我们检查该实体是否碰触了屏幕的边缘。然而,在这种情况下,游戏通知所有实体的游戏逻辑需要运行。稍后,我们会调整外星人的移动实现。
学软件开发,到蜂鸟科技!
超强的师资力量 、完善的课程体系 、超低的培训价格 、真实的企业项目。
网址:www.ntcsoft.com
电话:0371-63839606
郑州软件开发兴趣小组群:38236716
posted on 2010-11-25 23:55
whistler 阅读(386)
评论(0) 编辑 收藏