func (self *TopDownTestScene) SwapInput(event events.Event) {
	log.Println("Swap Input!")

	if !event.Pressed {
		return
	}

	if self.inputPlayer {
		self.playerCube.RemoveComponent(components.INPUT)
		components.GetTransform(self.playerCube).Halt()

		self.game.Camera.AddComponent(FixedCameraInput)

		self.inputPlayer = false
		self.topDownCamera.PauseTracking()

		log.Println("[Camera] Player now", self.playerCube)
	} else {
		self.game.Camera.RemoveComponent(components.INPUT)
		components.GetTransform(self.game.Camera.Entity).Halt()

		self.playerCube.AddComponent(FixedYInput)

		self.inputPlayer = true
		self.topDownCamera.ResumeTracking()

		log.Println("[Player] Player now", self.playerCube)
	}
}
예제 #2
0
func (self *TexturedCube) Setup() {
	self.theCube = core.NewEntity()
	self.theCube.Name = "Textured Cube"
	self.theCube.AddComponent(new(components.Visual))

	self.colorCube = core.NewEntity()
	self.colorCube.Name = "Colored Cube"
	self.colorCube.AddComponent(&components.Visual{
		MaterialName: "only_color",
		MeshName:     "ColorIndexCube",
	})

	transform := components.GetTransform(self.theCube)
	transform.Position = math3d.Vector{0, 0, -10}
	transform.Scale = math3d.Vector{2, 2, 2}
	transform.Speed = math3d.Vector{5, 5, 5}

	transform = components.GetTransform(self.colorCube)
	transform.Position = math3d.Vector{0, 0, -5}

	//	transform.MoveRelativeToRotation = true
	//	self.theCube.AddComponent(&components.Input{
	//		Mapping: FPSMapping,
	//	})

	skybox := factories.SkyBox("stevecube", self.game.Camera)

	self.game.RegisterEntity(skybox)
	self.game.RegisterEntity(self.theCube)
	self.game.RegisterEntity(self.colorCube)
}
func (self *TopDownTestScene) Setup() {
	self.game.RegisterEntity(factories.SkyBox("stevecube", self.game.Camera))

	self.levelVolume = &volume.FunctionVolume{
		func(x, y, z float32) float32 {
			if y > 5 && (x > 3 && x < 47) && (z > 3 && z < 47) {
				return -1
			} else {
				return 1
			}
		},
	}

	volumeMesh := volume.MarchingCubes(self.levelVolume, math3d.Vector{50, 10, 50}, 0.5)
	volumeMesh.Name = "Level Mesh"

	self.levelEntity = core.NewEntity()
	self.levelEntity.Name = "Level Geometry"
	self.levelEntity.AddComponent(&components.Visual{
		Mesh:         volumeMesh,
		MaterialName: "only_color",
	})

	self.game.RegisterEntity(self.levelEntity)

	self.game.Camera.AddComponent(&components.Input{
		Mapping: FPSMapping,
	})

	// Get the camera facing downwards
	cameraTransform := components.GetTransform(self.game.Camera.Entity)
	cameraTransform.Position = math3d.Vector{25, 10, 25}
	cameraTransform.CurrentPitch = 90
	cameraTransform.Speed = math3d.Vector{8, 8, 8}
	cameraTransform.MoveRelativeToRotation = false

	// Our unit we'll control
	self.playerCube = core.NewEntityAt(math3d.Vector{25, 6, 25})
	self.playerCube.Name = "The Player"
	self.playerCube.AddComponent(&components.Visual{})

	playerTransform := components.GetTransform(self.playerCube)
	playerTransform.Scale = math3d.Vector{0.25, 0.5, 0.25}
	playerTransform.Speed = math3d.Vector{3, 3, 3}
	playerTransform.MoveRelativeToRotation = false

	self.topDownCamera = NewTopDownCamera(self.game.Camera)
	self.topDownCamera.SetTrackingHeight(5)
	self.topDownCamera.TrackEntity(self.playerCube)

	self.game.RegisterEntity(self.playerCube)

	self.game.Keyboard.OnKey(input.KeySpace, func(event events.Event) { self.SwapInput(event) })

	// Start by controlling the player unit. Game defaults to controlling the camera
	self.SwapInput(events.Event{Pressed: true})
}
예제 #4
0
func (self *Transform) Update(deltaT float32) {
	var transform *components.Transform

	for _, entity := range self.entitySet.Entities() {
		transform = components.GetTransform(entity)

		if transform.UsingPositionOf == nil {
			self.processMovement(deltaT, transform)
			self.processRotation(deltaT, transform)
		} else {
			transform.Position = components.GetTransform(transform.UsingPositionOf).Position
		}
	}
}
예제 #5
0
func (self *Level) Generate() *core.Entity {
	// A square arena with walls
	self.volume = &volume.FunctionVolume{
		func(x, y, z float32) float32 {
			if y > 5 && (x > 3 && x < 47) && (z > 3 && z < 47) {
				return -1
			} else {
				return 1
			}
		},
	}

	volumeMesh := volume.MarchingCubes(self.volume, math3d.Vector{50, 10, 50}, 0.5)
	volumeMesh.Name = "Level Mesh"

	self.entity = core.NewEntity()
	self.entity.Name = "Level Geometry"
	self.entity.AddComponent(&components.Visual{
		Mesh:         volumeMesh,
		MaterialName: "only_color",
	})

	transform := components.GetTransform(self.entity)
	transform.Position = math3d.Vector{-25, -10, -25}

	return self.entity
}
// Make the entity always look towards the direction of the mouse cursor
// Always rotate around +Y (yaw)
func fixedYMouseMoved(entity components.ComponentHolder, event events.Event) {
	transform := components.GetTransform(entity)

	transform.CurrentYaw = math3d.RadToDeg(
		math3d.Atan2(float32(event.MouseYDiff), float32(event.MouseXDiff)),
	)*-1 + 90
}
예제 #7
0
func (self *Player) initializeComponents() {
	topDownInput := &components.Input{
		Mapping: components.InputEventMap{
			events.MoveForward:  self.moveForward,
			events.MoveBackward: self.moveBackward,
			events.MoveLeft:     self.moveLeft,
			events.MoveRight:    self.moveRight,
			events.MouseMove:    self.faceMouse,
		},
		Polling: []events.EventType{
			events.MoveForward,
			events.MoveBackward,
			events.MoveLeft,
			events.MoveRight,
		},
	}

	self.entity.AddComponent(&components.Visual{})
	self.entity.AddComponent(topDownInput)

	transform := components.GetTransform(self.entity)
	transform.Scale = math3d.Vector{0.25, 0.5, 0.25}
	transform.Speed = math3d.Vector{3, 3, 3}
	transform.MoveRelativeToRotation = false
}
예제 #8
0
func (self *Player) faceMouse(_ components.ComponentHolder, event events.Event) {
	transform := components.GetTransform(self.entity)

	transform.CurrentYaw = math3d.RadToDeg(
		math3d.Atan2(float32(event.MouseYDiff), float32(event.MouseXDiff)),
	)*-1 + 90
}
예제 #9
0
// NewEntityAt sets up a new Entity for use in the app and sets the
// initial Transform component's Position to the given Vector
func NewEntityAt(startingPosition math3d.Vector) *Entity {
	entity := NewEntity()
	transform := components.GetTransform(entity)
	transform.Position = startingPosition

	return entity
}
예제 #10
0
func Test_Update_CopiesPositionFromLinkedEntity(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	followee := core.NewEntity()
	followeeTransform := components.GetTransform(followee)
	followeeTransform.Position = math3d.Vector{10, 11, -12}

	transform := components.GetTransform(entity)
	transform.UsingPositionOf = followee

	behavior.Update(1)

	assert.Equal(t, math3d.Vector{10, 11, -12}, transform.Position)
}
예제 #11
0
// UpdatePosition calculates where this camera needs to be to stay tracking
// on the Entity, handling any potential changes of the Entity's position
func (self *TopDownCamera) UpdatePosition() {
	if self.currentlyTracking {
		entityPosition := components.GetTransform(self.trackingEntity).Position
		entityPosition.Y += self.trackingHeight

		self.camera.SetPosition(entityPosition)
	}
}
예제 #12
0
// ResumeTracking moves the camera back to the Entity being tracked and resumes
// camera position updates
func (self *TopDownCamera) ResumeTracking() {
	aboveEntity := components.GetTransform(self.trackingEntity).Position
	aboveEntity.Y += self.trackingHeight

	self.camera.AddComponent(
		components.NewPositionAnimation(
			aboveEntity, 0.5, func() { self.currentlyTracking = true },
		),
	)
}
예제 #13
0
func NewCamera() *Camera {
	camera := new(Camera)
	camera.Entity = NewEntity()
	camera.Entity.Name = "Camera"

	camera.transform = components.GetTransform(camera.Entity)
	camera.transform.MoveRelativeToRotation = true

	return camera
}
예제 #14
0
func (self *VolumeScene) Setup() {
	skybox := factories.SkyBox("stevecube", self.game.Camera)
	self.game.RegisterEntity(skybox)

	self.game.Camera.AddComponent(FPSInput)

	self.game.Camera.SetSpeed(math3d.Vector{5, 5, 5})
	self.game.Camera.LookAt(math3d.Vector{0, 0, -5})

	self.game.Keyboard.OnKey(input.KeyJ, func(e events.Event) {
		if e.Pressed {
			self.marchingCubeSize -= 0.1

			if self.marchingCubeSize <= 0 {
				self.marchingCubeSize = 0.1
			} else {
				self.rebuildVolume()
			}
		}
	})

	self.game.Keyboard.OnKey(input.KeyK, func(e events.Event) {
		if e.Pressed {
			self.marchingCubeSize += 0.1

			self.rebuildVolume()
		}
	})

	self.cubeVolume = &volume.FunctionVolume{
		// A sphere!
		func(x, y, z float32) float32 {
			// Translate to treat middle of the volume as 0,0,0
			// Basically I want 0,0,0 of the volume to act like -25, -25, -25, so that
			// the center point of the sphere is at 25, 25, 25 in the volume,
			// then check the equation against the radius of the sphere.
			tX := x - 25
			tY := y - 25
			tZ := z - 25

			return -(tX*tX + tY*tY + tZ*tZ - 20)
		},
	}

	self.volumeEntity = core.NewEntity()
	self.volumeEntity.Name = "cube volume"

	self.rebuildVolume()

	// Move the volume into view of the starting camera
	transform := components.GetTransform(self.volumeEntity)
	transform.Position = math3d.Vector{-25, -25, -40}

	self.game.RegisterEntity(self.volumeEntity)
}
예제 #15
0
func Test_SkyBox(t *testing.T) {
	camera := core.NewCamera()
	skybox := SkyBox("testMap", camera)

	visual := components.GetVisual(skybox)
	transform := components.GetTransform(skybox)

	assert.Equal(t, "Skybox testMap", skybox.Name)
	assert.Equal(t, "testMap", visual.MaterialName)
	assert.Equal(t, camera.Entity, transform.UsingPositionOf)
}
예제 #16
0
func Test_Update_UpdatesAPositionAnimationOverTime(t *testing.T) {
	behavior, entityDb := getTestAnimation()

	entity := core.NewEntity()
	entity.AddComponent(
		components.NewPositionAnimation(math3d.Vector{2, 2, 2}, 1, func() {}),
	)
	entityDb.RegisterEntity(entity)

	// Move half way
	behavior.Update(0.5)

	transform := components.GetTransform(entity)
	assert.Equal(t, math3d.Vector{1, 1, 1}, transform.Position)

	// Move the rest of the way
	behavior.Update(0.5)

	transform = components.GetTransform(entity)
	assert.Equal(t, math3d.Vector{2, 2, 2}, transform.Position)
}
예제 #17
0
func Test_Update_AppliesEulerAngles(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	transform := components.GetTransform(entity)
	startingQuat := transform.Rotation
	transform.CurrentPitch = 45

	behavior.Update(1)
	assert.NotEqual(t, startingQuat, transform.Rotation)
}
func Test_MouseMove(t *testing.T) {
	event := events.Event{
		MouseXDiff: 30,
		MouseYDiff: 40,
	}

	entity := core.NewEntity()
	transform := components.GetTransform(entity)

	FPSMapping[events.MouseMove](entity, event)

	assert.Equal(t, 15, transform.CurrentYaw)
	assert.Equal(t, 20, transform.CurrentPitch)
}
func Test_MouseMove_ConstrainsYaw(t *testing.T) {
	event := events.Event{
		MouseXDiff: 40,
		MouseYDiff: 0,
	}

	entity := core.NewEntity()
	transform := components.GetTransform(entity)
	transform.CurrentYaw = 350

	FPSMapping[events.MouseMove](entity, event)

	assert.Equal(t, 10, transform.CurrentYaw)
}
예제 #20
0
func Test_Update_AppliesSpeedToMovingDir(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	transform := components.GetTransform(entity)
	transform.Moving(math3d.Vector{1, 0, 0})
	transform.Speed = math3d.Vector{2, 2, 2}

	// Time passed? change!
	behavior.Update(0.5)
	assert.Equal(t, math3d.Vector{1, 0, 0}, transform.Position)
}
func Test_MouseMove_ClampsPitch(t *testing.T) {
	event := events.Event{
		MouseXDiff: 0,
		MouseYDiff: 40,
	}

	entity := core.NewEntity()
	transform := components.GetTransform(entity)
	transform.CurrentPitch = 80

	FPSMapping[events.MouseMove](entity, event)

	assert.Equal(t, 89, transform.CurrentPitch)
}
예제 #22
0
// SkyBox returns an Entity that is set up as a SkyBox. The material given
// needs to be the name of a cube-map Material definition. The resulting entity
// will be position-locked to the passed in camera so that it never looks like
// it's moving.
func SkyBox(skyboxMaterial string, camera *core.Camera) *core.Entity {
	entity := core.NewEntity()
	entity.Name = "Skybox " + skyboxMaterial

	visual := new(components.Visual)
	visual.MeshName = "SkyBoxMesh"
	visual.MaterialName = skyboxMaterial

	transform := components.GetTransform(entity)
	transform.UsingPositionOf = camera.Entity
	transform.Scale = math3d.Vector{20, 20, 20}

	entity.AddComponent(visual)

	return entity
}
예제 #23
0
func Test_Update_MovesWithRotationIfSoFlagged(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	transform := components.GetTransform(entity)
	transform.Moving(math3d.Vector{1, 0, 0})
	transform.Speed = math3d.Vector{1, 1, 1}
	transform.Rotation = math3d.Quaternion{0, 0, 1, 0}
	transform.MoveRelativeToRotation = true

	// Time passed? change!
	behavior.Update(1)
	assert.Equal(t, math3d.Vector{-1, 0, 0}, transform.Position)
}
예제 #24
0
func Test_Update_UpdatesOverMultipleSeconds(t *testing.T) {
	behavior, entityDb := getTestAnimation()

	entity := core.NewEntity()
	entity.AddComponent(
		components.NewPositionAnimation(math3d.Vector{10, 10, 10}, 10, func() {}),
	)
	entityDb.RegisterEntity(entity)

	var i float32 = 1
	for ; i <= 10; i++ {
		behavior.Update(1)

		transform := components.GetTransform(entity)
		assert.Equal(t, math3d.Vector{i, i, i}, transform.Position)
	}
}
예제 #25
0
func Test_Update_AppliesMovementDirOnTransforms(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	transform := components.GetTransform(entity)
	transform.Moving(math3d.Vector{1, 0, 0})

	// No time passed? no change
	behavior.Update(0)
	assert.Equal(t, math3d.Vector{0, 0, 0}, transform.Position)

	// Time passed? change!
	behavior.Update(1)
	assert.Equal(t, math3d.Vector{1, 0, 0}, transform.Position)
}
예제 #26
0
func Test_Update_AppliesRotationDir(t *testing.T) {
	behavior, entityDb := getTestTransform()

	entity := core.NewEntity()
	entityDb.RegisterEntity(entity)

	transform := components.GetTransform(entity)
	transform.Rotating(math3d.Vector{0, 1, 0})

	startingQuat := transform.Rotation

	// No time passed? no change
	behavior.Update(0)
	assert.Equal(t, startingQuat, transform.Rotation)

	// Time passed? change!
	behavior.Update(1)
	assert.NotEqual(t, startingQuat, transform.Rotation)
}
func Test_FixedCamera_CardinalMovement(t *testing.T) {
	event := events.Event{}

	for _, testValue := range panningCardinalTests {
		entity := core.NewEntity()
		transform := components.GetTransform(entity)

		// Set on pressed
		event.Pressed = true

		FixedCameraMapping[testValue.event](entity, event)
		assert.Equal(t, testValue.expectedDir, transform.MoveDir())

		// And undo the change on key release
		event.Pressed = false

		FixedCameraMapping[testValue.event](entity, event)
		assert.Equal(t, math3d.Vector{0, 0, 0}, transform.MoveDir())
	}
}
func Test_Turning(t *testing.T) {
	event := events.Event{}

	for _, testValue := range turnTests {
		entity := core.NewEntity()
		transform := components.GetTransform(entity)

		// Set on pressed
		event.Pressed = true

		FPSMapping[testValue.event](entity, event)
		assert.Equal(t, testValue.expectedDir, transform.RotateDir())

		// And undo the change on key release
		event.Pressed = false

		FPSMapping[testValue.event](entity, event)
		assert.Equal(t, math3d.Vector{0, 0, 0}, transform.RotateDir())
	}
}
예제 #29
0
// Simple linear animation between two positions over time
func animatePosition(deltaT float32, entity *core.Entity) bool {
	animation := components.GetAnimation(entity)
	transform := components.GetTransform(entity)

	// Move more of this into the Animation?
	// Basically we are building this to figure out the distance we need to travel
	// in the current tick to have consistent, linear movement over the time period requested.
	// Probably better ways of calculating this.
	if animation.CurrentTweenTick == 0 {
		animation.TweenStartAt = transform.Position
	}

	animation.CurrentTweenTick += deltaT

	tweenPercent := deltaT / animation.TweenTime

	movePerFrame := animation.TweenTo.Sub(animation.TweenStartAt).Scale(tweenPercent)
	transform.Position = transform.Position.Add(movePerFrame)

	return animation.CurrentTweenTick >= animation.TweenTime
}
예제 #30
0
// Update is called every Game tick
func (self *Graphical) Update(camera *core.Camera, deltaT float32) {
	self.renderer.BeginRender()
	var visual *components.Visual

	renderQueue := render.NewRenderQueue()

	renderQueue.ProjectionMatrix = camera.ProjectionMatrix()
	renderQueue.ViewMatrix = camera.ViewMatrix()

	for _, entity := range self.entitySet.Entities() {
		visual = components.GetVisual(entity)

		renderQueue.Add(render.RenderOperation{
			Mesh:      self.meshFromVisual(visual),
			Material:  self.materialLoader.Get(visual.MaterialName),
			Transform: components.GetTransform(entity).TransformMatrix(),
		})
	}

	self.renderer.Render(renderQueue)

	self.renderer.FinishRender()
}