Example #1
0
// Compute an entity's new position.
// Returns an EntityDiff if the entity has changed, nil otherwise.
func (m *Mover) UpdateEntity(ent *entity.Entity, now message.AbsoluteTick) (req *entity.UpdateRequest, collidesWith interface{}) {
	// TODO: remove Mover.lastUpdates?
	var last message.AbsoluteTick
	var ok bool
	if last, ok = m.lastUpdates[ent.Id]; !ok {
		last = now
	}

	m.lastUpdates[ent.Id] = now
	dt := time.Duration(now-last) * clock.TickDuration // Convert to seconds
	if dt == 0 {
		return
	}
	if dt < 0 {
		return // TODO: figure out if it's the right thing to do here
	}

	speed := ent.Speed
	pos := ent.Position

	nextPos := speed.GetNextPosition(pos, dt)
	if nextPos == nil {
		return
	}

	// Check terrain
	// TODO: use brensenham algorithm
	// See http://tech-algorithm.com/articles/drawing-line-using-bresenham-algorithm/
	route := terrain.GetRouteBetween(pos, nextPos)

	stoppedAt, collidesWith := checkRoute(route, ent, m.engine.ctx.Terrain, m.engine.ctx.Entity.List())
	if stoppedAt != nil {
		// The entity has been stopped while moving
		nextPos = stoppedAt
	}

	newEnt := entity.New()
	newEnt.Id = ent.Id
	newEnt.Position = nextPos
	diff := &message.EntityDiff{Position: true}

	req = entity.NewUpdateRequest(now, newEnt, diff)
	return
}
Example #2
0
func (e *Engine) moveEntities(t message.AbsoluteTick) {
	for _, ent := range e.entity.List() {
		req, collidesWith := e.mover.UpdateEntity(ent, t)

		// [GAME-SPECIFIC] Destroy balls when they collide
		if collidesWith != nil && ent.Type == game.BallEntity {
			req := entity.NewDeleteRequest(t, ent.Id)
			if err := e.entity.AcceptRequest(req); err != nil {
				panic(err) // This shouldn't happen
			}

			// If the ball collides with a player, decrease his health
			if collidesWith, ok := collidesWith.(*message.Entity); ok && collidesWith.Type == game.PlayerEntity {
				sender := ent.Attributes[game.SenderAttr].(message.EntityId)
				if sender != collidesWith.Id {
					health := collidesWith.Attributes[game.HealthAttr].(game.Health)

					updated := entity.New()
					updated.Attributes[game.HealthAttr] = health - 1
					diff := message.NewEntityDiff()
					diff.Attributes = true
					req := entity.NewUpdateRequest(t, updated, diff)
					if err := e.entity.AcceptRequest(req); err != nil {
						panic(err) // This shouldn't happen
					}
				}
			}
			continue
		}

		if req != nil {
			// Let's assume mover already did all security checks
			if err := e.entity.AcceptRequest(req); err != nil {
				// This should not fail
				panic(err)
			}
		}
	}
}