Beispiel #1
0
func (e *Engine) processActionRequest(req *action.Request) bool {
	// [GAME-SPECIFIC] Handle action requests according to game rules
	switch req.Action.Id {
	case game.ThrowBallAction:
		log.Println("Accepting ball", req)

		initiator := e.entity.Get(req.Action.Initiator)
		ball := entity.New()
		ball.Type = game.BallEntity
		ball.Sprite = game.BallSprite
		ball.Position = initiator.Position
		ball.Speed.Norm = float64(e.config.DefaultBallSpeed)
		ball.Speed.Angle = float64(req.Action.Params[0].(float32))
		ball.Attributes[game.TicksLeftAttr] = e.config.DefaultBallLifespan
		ball.Attributes[game.SenderAttr] = initiator.Id
		r := entity.NewCreateRequest(req.GetTick(), ball)
		if err := e.entity.AcceptRequest(r); err != nil {
			// This shouldn't fail
			panic(err)
		}

		session := e.auth.GetSessionByEntity(req.Action.Initiator)

		// TODO: error handling
		e.clients[session.Id].Write(func(w io.Writer) error {
			return builder.SendEntityIdChange(w, req.Action.Params[1].(message.EntityId), ball.Id)
		})
	}

	return true
}
Beispiel #2
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
}
Beispiel #3
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)
			}
		}
	}
}