Beispiel #1
0
func (l *legacyShader) Pre() {
	Gl.Enable(Gl.BLEND)
	Gl.BlendFunc(Gl.SRC_ALPHA, Gl.ONE_MINUS_SRC_ALPHA)

	// Bind shader and buffer, enable attributes
	Gl.UseProgram(l.program)
	Gl.EnableVertexAttribArray(l.inPosition)
	Gl.EnableVertexAttribArray(l.inColor)

	if scaleOnResize {
		l.projectionMatrix[0] = 1 / (gameWidth / 2)
		l.projectionMatrix[4] = 1 / (-gameHeight / 2)
	} else {
		l.projectionMatrix[0] = 1 / (windowWidth / 2)   // TODO: canvasWidth
		l.projectionMatrix[4] = 1 / (-windowHeight / 2) // TODO: canvasHeight
	}

	if l.cameraEnabled {
		l.viewMatrix[1], l.viewMatrix[0] = math.Sincos(cam.angle * math.Pi / 180)
		l.viewMatrix[3] = -l.viewMatrix[1]
		l.viewMatrix[4] = l.viewMatrix[0]
		l.viewMatrix[6] = -cam.x
		l.viewMatrix[7] = -cam.y
		l.viewMatrix[8] = cam.z
	} else {
		l.viewMatrix[6] = -1 / l.projectionMatrix[0]
		l.viewMatrix[7] = 1 / l.projectionMatrix[4]
	}

	Gl.UniformMatrix3fv(l.matrixProjection, false, l.projectionMatrix)
	Gl.UniformMatrix3fv(l.matrixView, false, l.viewMatrix)
	Gl.Uniform2f(l.inViewport, gameWidth, gameHeight) // TODO: canvasWidth/Height
}
Beispiel #2
0
func (s *basicShader) Pre() {
	Gl.Enable(Gl.BLEND)
	Gl.BlendFunc(Gl.SRC_ALPHA, Gl.ONE_MINUS_SRC_ALPHA)

	// Enable shader and buffer, enable attributes in shader
	Gl.UseProgram(s.program)
	Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, s.indexVBO)
	Gl.EnableVertexAttribArray(s.inPosition)
	Gl.EnableVertexAttribArray(s.inTexCoords)
	Gl.EnableVertexAttribArray(s.inColor)

	if scaleOnResize {
		s.projectionMatrix[0] = 1 / (gameWidth / 2)
		s.projectionMatrix[4] = 1 / (-gameHeight / 2)
	} else {
		s.projectionMatrix[0] = 1 / (windowWidth / 2)
		s.projectionMatrix[4] = 1 / (-windowHeight / 2)
	}

	if s.cameraEnabled {
		s.viewMatrix[1], s.viewMatrix[0] = math.Sincos(cam.angle * math.Pi / 180)
		s.viewMatrix[3] = -s.viewMatrix[1]
		s.viewMatrix[4] = s.viewMatrix[0]
		s.viewMatrix[6] = -cam.x
		s.viewMatrix[7] = -cam.y
		s.viewMatrix[8] = cam.z
	} else {
		s.viewMatrix[6] = -1 / s.projectionMatrix[0]
		s.viewMatrix[7] = 1 / s.projectionMatrix[4]
	}

	Gl.UniformMatrix3fv(s.matrixProjection, false, s.projectionMatrix)
	Gl.UniformMatrix3fv(s.matrixView, false, s.viewMatrix)
}
Beispiel #3
0
func (s *basicShader) Draw(ren *RenderComponent, space *SpaceComponent) {
	if s.lastBuffer != ren.buffer || ren.buffer == nil {
		s.updateBuffer(ren)

		Gl.BindBuffer(Gl.ARRAY_BUFFER, ren.buffer)
		Gl.VertexAttribPointer(s.inPosition, 2, Gl.FLOAT, false, 20, 0)
		Gl.VertexAttribPointer(s.inTexCoords, 2, Gl.FLOAT, false, 20, 8)
		Gl.VertexAttribPointer(s.inColor, 4, Gl.UNSIGNED_BYTE, true, 20, 16)

		s.lastBuffer = ren.buffer
	}

	if s.lastTexture != ren.Drawable.Texture() {
		Gl.BindTexture(Gl.TEXTURE_2D, ren.Drawable.Texture())

		s.lastTexture = ren.Drawable.Texture()
	}

	if s.lastRepeating != ren.Repeat {
		var val int
		switch ren.Repeat {
		case CLAMP_TO_EDGE:
			val = Gl.CLAMP_TO_EDGE
		case CLAMP_TO_BORDER:
			val = Gl.CLAMP_TO_EDGE
		case REPEAT:
			val = Gl.REPEAT
		case MIRRORED_REPEAT:
			val = Gl.MIRRORED_REPEAT
		}

		Gl.TexParameteri(Gl.TEXTURE_2D, Gl.TEXTURE_WRAP_S, val)
		Gl.TexParameteri(Gl.TEXTURE_2D, Gl.TEXTURE_WRAP_T, val)
	}

	if space.Rotation != 0 {
		sin, cos := math.Sincos(space.Rotation * math.Pi / 180)

		s.modelMatrix[0] = ren.Scale.X * cos
		s.modelMatrix[1] = ren.Scale.X * sin
		s.modelMatrix[3] = ren.Scale.Y * -sin
		s.modelMatrix[4] = ren.Scale.Y * cos
	} else {
		s.modelMatrix[0] = ren.Scale.X
		s.modelMatrix[1] = 0
		s.modelMatrix[3] = 0
		s.modelMatrix[4] = ren.Scale.Y
	}

	s.modelMatrix[6] = space.Position.X
	s.modelMatrix[7] = space.Position.Y

	Gl.UniformMatrix3fv(s.matrixModel, false, s.modelMatrix)

	Gl.DrawElements(Gl.TRIANGLES, 6, Gl.UNSIGNED_SHORT, 0)
}
Beispiel #4
0
// AABB returns the minimum and maximum point for the given SpaceComponent. It hereby takes into account the
// rotation of the Component - it may very well be that the Minimum as given by AABB, is smaller than the Position
// of the object (i.e. when rotated). As this method takes into account the rotation, it should be used only when
// required.
func (sc SpaceComponent) AABB() AABB {
	if sc.Rotation == 0 {
		return AABB{
			Min: sc.Position,
			Max: Point{sc.Position.X + sc.Width, sc.Position.Y + sc.Height},
		}
	}

	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)
	xmin := sc.Position.X
	xmax := sc.Position.X + sc.Width*cos - sc.Height*sin
	ymin := sc.Position.Y
	ymax := sc.Position.Y + sc.Height*cos + sc.Width*sin

	var (
		X_MIN, X_MAX, Y_MIN, Y_MAX float32
	)

	if xmin < xmax {
		X_MIN = xmin
		X_MAX = xmax
	} else {
		X_MIN = xmax
		X_MAX = xmin
	}

	if ymin < ymax {
		Y_MIN = ymin
		Y_MAX = ymax
	} else {
		Y_MIN = ymax
		Y_MAX = ymin
	}

	return AABB{Point{X_MIN, Y_MIN}, Point{X_MAX, Y_MAX}}
}
Beispiel #5
0
func (l *legacyShader) Draw(ren *RenderComponent, space *SpaceComponent) {
	if l.lastBuffer != ren.buffer || ren.buffer == nil {
		l.updateBuffer(ren, space)

		Gl.BindBuffer(Gl.ARRAY_BUFFER, ren.buffer)
		Gl.VertexAttribPointer(l.inPosition, 2, Gl.FLOAT, false, 12, 0)
		Gl.VertexAttribPointer(l.inColor, 4, Gl.UNSIGNED_BYTE, true, 12, 8)

		l.lastBuffer = ren.buffer
	}

	if space.Rotation != 0 {
		sin, cos := math.Sincos(space.Rotation * math.Pi / 180)

		l.modelMatrix[0] = ren.Scale.X * cos
		l.modelMatrix[1] = ren.Scale.X * sin
		l.modelMatrix[3] = ren.Scale.Y * -sin
		l.modelMatrix[4] = ren.Scale.Y * cos
	} else {
		l.modelMatrix[0] = ren.Scale.X
		l.modelMatrix[1] = 0
		l.modelMatrix[3] = 0
		l.modelMatrix[4] = ren.Scale.Y
	}

	l.modelMatrix[6] = space.Position.X
	l.modelMatrix[7] = space.Position.Y

	Gl.UniformMatrix3fv(l.matrixModel, false, l.modelMatrix)

	switch shape := ren.Drawable.(type) {
	case Triangle:
		Gl.Uniform2f(l.inRadius, 0, 0)
		Gl.DrawArrays(Gl.TRIANGLES, 0, 3)

		if shape.BorderWidth > 0 {
			borderWidth := shape.BorderWidth
			if l.cameraEnabled {
				borderWidth /= cam.z
			}
			Gl.LineWidth(borderWidth)
			Gl.DrawArrays(Gl.LINE_LOOP, 3, 3)
		}
	case Rectangle:
		Gl.Uniform2f(l.inRadius, 0, 0)
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, l.indicesRectanglesVBO)
		Gl.DrawElements(Gl.TRIANGLES, 6, Gl.UNSIGNED_SHORT, 0)

		if shape.BorderWidth > 0 {
			borderWidth := shape.BorderWidth
			if l.cameraEnabled {
				borderWidth /= cam.z
			}
			Gl.LineWidth(borderWidth)
			Gl.DrawArrays(Gl.LINE_LOOP, 4, 4)
		}
	case Circle:
		Gl.Uniform1f(l.inBorderWidth, shape.BorderWidth/cam.z)
		if shape.BorderWidth > 0 {
			r, g, b, a := shape.BorderColor.RGBA()
			Gl.Uniform4f(l.inBorderColor, float32(r>>8), float32(g>>8), float32(b>>8), float32(a>>8))
		}
		Gl.Uniform2f(l.inRadius, (space.Width/2)/cam.z, (space.Height/2)/cam.z)
		Gl.Uniform2f(l.inCenter, space.Width/2, space.Height/2)
		Gl.BindBuffer(Gl.ELEMENT_ARRAY_BUFFER, l.indicesRectanglesVBO)
		Gl.DrawElements(Gl.TRIANGLES, 6, Gl.UNSIGNED_SHORT, 0)
	case ComplexTriangles:
		Gl.Uniform2f(l.inRadius, 0, 0)
		Gl.DrawArrays(Gl.TRIANGLES, 0, len(shape.Points))

		if shape.BorderWidth > 0 {
			borderWidth := shape.BorderWidth
			if l.cameraEnabled {
				borderWidth /= cam.z
			}
			Gl.LineWidth(borderWidth)
			Gl.DrawArrays(Gl.LINE_LOOP, len(shape.Points), len(shape.Points))
		}
	default:
		unsupportedType()
	}
}
Beispiel #6
0
func (m *MouseSystem) Update(dt float32) {
	// Translate Mouse.X and Mouse.Y into "game coordinates"
	m.mouseX = Mouse.X*cam.z*(gameWidth/windowWidth) + cam.x - (gameWidth/2)*cam.z
	m.mouseY = Mouse.Y*cam.z*(gameHeight/windowHeight) + cam.y - (gameHeight/2)*cam.z // TODO maybe other width/height?

	// Rotate if needed
	if cam.angle != 0 {
		sin, cos := math.Sincos(cam.angle * math.Pi / 180)
		m.mouseX, m.mouseY = m.mouseX*cos+m.mouseY*sin, m.mouseY*cos-m.mouseX*sin
	}

	for _, e := range m.entities {
		// Reset all values except these
		*e.MouseComponent = MouseComponent{
			Track:           e.MouseComponent.Track,
			Hovered:         e.MouseComponent.Hovered,
			startedDragging: e.MouseComponent.startedDragging,
		}

		if e.MouseComponent.Track {
			// track mouse position so that systems that need to stay on the mouse
			// position can do it (think an RTS when placing a new building and
			// you get a ghost building following your mouse until you click to
			// place it somewhere in your world.
			e.MouseComponent.MouseX = m.mouseX
			e.MouseComponent.MouseY = m.mouseY
		}

		mx := m.mouseX
		my := m.mouseY

		if e.SpaceComponent == nil {
			continue // with other entities
		}

		if e.RenderComponent != nil {
			// Hardcoded special case for the HUD | TODO: make generic instead of hardcoding
			if e.RenderComponent.shader == HUDShader {
				mx = Mouse.X
				my = Mouse.Y
			}
		}

		// if the Mouse component is a tracker we always update it
		// Check if the X-value is within range
		// and if the Y-value is within range
		pos := e.SpaceComponent.AABB()

		if e.MouseComponent.Track || e.MouseComponent.startedDragging ||
			mx > pos.Min.X && mx < pos.Max.X && my > pos.Min.Y && my < pos.Max.Y {

			e.MouseComponent.Enter = !e.MouseComponent.Hovered
			e.MouseComponent.Hovered = true
			e.MouseComponent.Released = false

			if !e.MouseComponent.Track {
				// If we're tracking, we've already set these
				e.MouseComponent.MouseX = mx
				e.MouseComponent.MouseY = my
			}

			switch Mouse.Action {
			case PRESS:
				switch Mouse.Button {
				case MouseButtonLeft:
					e.MouseComponent.startedDragging = true
					e.MouseComponent.Clicked = true
				case MouseButtonRight:
					e.MouseComponent.RightClicked = true
				}
				m.mouseDown = true
			case RELEASE:
				switch Mouse.Button {
				case MouseButtonLeft:
					e.MouseComponent.Released = true
				case MouseButtonRight:
					e.MouseComponent.RightReleased = true
				}
			case MOVE:
				if m.mouseDown && e.MouseComponent.startedDragging {
					e.MouseComponent.Dragged = true
				}
			}
		} else {
			if e.MouseComponent.Hovered {
				e.MouseComponent.Leave = true
			}
			e.MouseComponent.Hovered = false
		}

		if Mouse.Action == RELEASE {
			// dragging stops as soon as one of the currently pressed buttons
			// is released
			e.MouseComponent.Dragged = false
			e.MouseComponent.startedDragging = false
			// mouseDown goes false as soon as one of the pressed buttons is
			// released. Effectively ending any dragging
			m.mouseDown = false
		}

		// propagate the modifiers to the mouse component so that game
		// implementers can take different decisions based on those
		e.MouseComponent.Modifier = Mouse.Modifer
	}
}