Got a field of bricks

main
Sean Hickey 2021-09-03 22:33:30 -07:00
parent d38139e7ec
commit ebb429819a
10 changed files with 309 additions and 121 deletions

154
main.go
View File

@ -12,6 +12,7 @@ import (
"github.com/go-gl/mathgl/mgl32"
"github.com/veandco/go-sdl2/sdl"
"gitea.wisellama.rocks/carpy-breakout/pkg/breakout"
"gitea.wisellama.rocks/carpy-breakout/pkg/game_window"
"gitea.wisellama.rocks/carpy-breakout/pkg/gl_objects"
)
@ -66,36 +67,48 @@ func run() {
defer gameWindow.Destroy()
camera := gl_objects.NewCamera(gameWindow.GLProgram)
camera.Position = mgl32.Vec3{0, 0, 10}
camera.Position = mgl32.Vec3{0, 0, 30}
gameWindow.SetCamera(camera)
gameWindow.AddObject(camera)
// textureId, err := gl_helpers.NewTexture("square.png")
// if err != nil {
// log.Fatal(err)
// }
box := gl_objects.NewBox(6.0, 4.0, 2.0, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{1, 0, 0})
box.GLInit(gameWindow.GLProgram)
//box.SetTexture(texture)
// TODO bounding box
targets := breakout.NewTargets(5, 4, mgl32.Vec3{-10, 4, 0})
targets.GLInit(gameWindow.GLProgram)
for _, brick := range targets.Bricks {
gameWindow.AddObject(brick)
}
paddle := gl_objects.NewBox(6.0, 1.0, 4.0, mgl32.Vec3{0, -10, 0}, mgl32.Vec3{0, 1, 0})
paddle.GLInit(gameWindow.GLProgram)
gameWindow.AddObject(paddle)
gameWindow.SetPaddle(paddle)
ball := gl_objects.NewBox(1, 1, 1, mgl32.Vec3{-8, -2, 0}, mgl32.Vec3{1, 1, 1})
ball.GLInit(gameWindow.GLProgram)
gameWindow.AddObject(ball)
// Global options after setup is all done
gl.ClearColor(0.0, 0.0, 0.0, 1.0)
gl.Enable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.LineWidth(3.0)
gl.LineWidth(2.0)
running := true
for running {
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
camera.Update()
camera.Draw()
box.Update()
box.Draw()
gameWindow.Update()
gameWindow.Draw()
gameWindow.SDLWindow.GLSwap()
running = handleEvents(running, gameWindow, &camera)
running = handleEvents(running, gameWindow)
sdl.Delay(16)
}
}
@ -110,7 +123,7 @@ func setupLogging() {
log.Println("=== START ===")
}
func handleEvents(running bool, gameWindow *game_window.GameWindow, camera *gl_objects.Camera) bool {
func handleEvents(running bool, gameWindow *game_window.GameWindow) bool {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch t := event.(type) {
case *sdl.WindowEvent:
@ -120,7 +133,11 @@ func handleEvents(running bool, gameWindow *game_window.GameWindow, camera *gl_o
running = false
case *sdl.MouseMotionEvent:
if t.XRel != 0 || t.YRel != 0 {
camera.Rotate(t.XRel, t.YRel, 0)
if gameWindow.IsFreelookOn() {
gameWindow.Camera.Rotate(t.XRel, t.YRel, 0)
} else {
gameWindow.MovePaddle(t.XRel, t.YRel)
}
}
case *sdl.MouseButtonEvent:
fmt.Printf("[%d ms] MouseButton\ttype:%d\tid:%d\tx:%d\ty:%d\tbutton:%d\tstate:%d\n",
@ -138,67 +155,80 @@ func handleEvents(running bool, gameWindow *game_window.GameWindow, camera *gl_o
gameWindow.ToggleFullscreen()
}
}
if t.Keysym.Sym == sdl.K_w {
if t.Keysym.Sym == sdl.K_l {
if t.Type == sdl.KEYDOWN {
camera.SetZVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetZVelocity(0)
gameWindow.ToggleWireframe()
}
}
if t.Keysym.Sym == sdl.K_a {
if t.Keysym.Sym == sdl.K_k {
if t.Type == sdl.KEYDOWN {
camera.SetXVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetXVelocity(0)
gameWindow.ToggleFreelook()
}
}
if t.Keysym.Sym == sdl.K_s {
if t.Type == sdl.KEYDOWN {
camera.SetZVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetZVelocity(0)
// Movement
if gameWindow.IsFreelookOn() {
if t.Keysym.Sym == sdl.K_w {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetZVelocity(1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetZVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_d {
if t.Type == sdl.KEYDOWN {
camera.SetXVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetXVelocity(0)
if t.Keysym.Sym == sdl.K_a {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetXVelocity(-1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetXVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_q {
if t.Type == sdl.KEYDOWN {
camera.SetYVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetYVelocity(0)
if t.Keysym.Sym == sdl.K_s {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetZVelocity(-1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetZVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_e {
if t.Type == sdl.KEYDOWN {
camera.SetYVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetYVelocity(0)
if t.Keysym.Sym == sdl.K_d {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetXVelocity(1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetXVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_z {
if t.Type == sdl.KEYDOWN {
camera.SetRotationVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetRotationVelocity(0)
if t.Keysym.Sym == sdl.K_q {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetYVelocity(-1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetYVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_x {
if t.Type == sdl.KEYDOWN {
camera.SetRotationVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetRotationVelocity(0)
if t.Keysym.Sym == sdl.K_e {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetYVelocity(1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetYVelocity(0)
}
}
}
if t.Keysym.Sym == sdl.K_LSHIFT {
if t.Type == sdl.KEYDOWN {
camera.SetFastMoveVelocity(2)
} else if t.Type == sdl.KEYUP {
camera.SetFastMoveVelocity(0)
if t.Keysym.Sym == sdl.K_z {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetRotationVelocity(-1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetRotationVelocity(0)
}
}
if t.Keysym.Sym == sdl.K_x {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetRotationVelocity(1)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetRotationVelocity(0)
}
}
if t.Keysym.Sym == sdl.K_LSHIFT {
if t.Type == sdl.KEYDOWN {
gameWindow.Camera.SetFastMoveVelocity(2)
} else if t.Type == sdl.KEYUP {
gameWindow.Camera.SetFastMoveVelocity(0)
}
}
}
}

40
pkg/breakout/brick.go Normal file
View File

@ -0,0 +1,40 @@
package breakout
import (
"github.com/go-gl/mathgl/mgl32"
"gitea.wisellama.rocks/carpy-breakout/pkg/gl_objects"
)
type Brick struct {
Box *gl_objects.Box
broken bool
}
func NewBrick(brickWidth, brickHeight, brickDepth float32, position, color mgl32.Vec3) *Brick {
brick := Brick{
Box: gl_objects.NewBox(brickWidth, brickHeight, brickDepth, position, color),
broken: false,
}
return &brick
}
func (b *Brick) Draw() {
if !b.broken {
b.Box.Draw()
}
}
func (b *Brick) GLInit(glProgram uint32) {
b.Box.GLInit(glProgram)
}
func (b *Brick) ToggleWireframe() {
b.Box.ToggleWireframe()
}
func (b *Brick) Update() {
if !b.broken {
b.Box.Update()
}
}

57
pkg/breakout/targets.go Normal file
View File

@ -0,0 +1,57 @@
package breakout
import (
"github.com/go-gl/mathgl/mgl32"
)
type Targets struct {
Rows int
Columns int
Bricks []*Brick
}
func NewTargets(numRows, numColumns int, lowerLeftPos mgl32.Vec3) *Targets {
targets := Targets{
Rows: numRows,
Columns: numColumns,
Bricks: make([]*Brick, numRows*numColumns),
}
var brickWidth float32 = 4.0
var brickHeight float32 = 1.0
var brickDepth float32 = 4.0
colors := make([]mgl32.Vec3, numColumns)
for i := 0; i < numColumns; i++ {
red := 0 + float32(i)/float32(numColumns)
blue := 1 - float32(i)/float32(numColumns)
colors[i] = mgl32.Vec3{red, 0, blue}
}
n := 0
for i := 0; i < numColumns; i++ {
for j := 0; j < numRows; j++ {
position := lowerLeftPos.Add(mgl32.Vec3{
float32(j) + float32(j)*brickWidth,
float32(i) + float32(i)*brickHeight,
0})
targets.Bricks[n] = NewBrick(brickWidth, brickHeight, brickDepth, position, colors[i])
n++
}
}
return &targets
}
func (t *Targets) GLInit(glProgram uint32) {
for _, brick := range t.Bricks {
brick.GLInit(glProgram)
}
}
func (t *Targets) Draw() {
for _, brick := range t.Bricks {
brick.Draw()
}
}

View File

@ -21,7 +21,13 @@ type GameWindow struct {
GLContext *sdl.GLContext
GLProgram uint32
GLObjects []gl_objects.GLObject
Camera *gl_objects.Camera
Paddle *gl_objects.Box
fullscreen bool
wireframe bool
freelook bool
}
func NewGameWindow(title string) (*GameWindow, error) {
@ -54,13 +60,16 @@ func NewGameWindow(title string) (*GameWindow, error) {
gameWindow.SDLWindow = window
gameWindow.GLProgram = program
gameWindow.fullscreen = false
gameWindow.WindowProjection()
return &gameWindow, err
}
func (w *GameWindow) AddObject(object gl_objects.GLObject) {
w.GLObjects = append(w.GLObjects, object)
}
func (w *GameWindow) Destroy() {
w.SDLWindow.Destroy()
sdl.GLDeleteContext(*w.GLContext)
@ -69,12 +78,18 @@ func (w *GameWindow) Destroy() {
func (w *GameWindow) ToggleFullscreen() {
if w.fullscreen {
w.SDLWindow.SetFullscreen(DefaultWindowFlags)
w.fullscreen = false
} else {
w.SDLWindow.SetFullscreen(FullscreenWindowFlags)
w.fullscreen = true
}
return
w.fullscreen = !w.fullscreen
}
func (w *GameWindow) ToggleFreelook() {
w.freelook = !w.freelook
}
func (w *GameWindow) IsFreelookOn() bool {
return w.freelook
}
func (w *GameWindow) WindowProjection() {
@ -85,25 +100,56 @@ func (w *GameWindow) WindowProjection() {
gl.Viewport(0, 0, width, height)
}
func GLInitVertexAttribs(glProgram uint32, textureOn bool) {
var sizeofFloat int32 = 4
stride := gl_objects.VertexSize * sizeofFloat
vertAttrib := uint32(gl.GetAttribLocation(glProgram, gl.Str("vert\x00")))
gl.EnableVertexAttribArray(vertAttrib)
gl.VertexAttribPointerWithOffset(vertAttrib, 3, gl.FLOAT, false, stride, uintptr(0))
func (w *GameWindow) MovePaddle(x, y int32) {
log.Printf("Moving paddle: %v, %v\n", x, y)
}
vertColorAttrib := uint32(gl.GetAttribLocation(glProgram, gl.Str("vertColor\x00")))
gl.EnableVertexAttribArray(vertColorAttrib)
gl.VertexAttribPointerWithOffset(vertColorAttrib, 3, gl.FLOAT, false, stride, uintptr(3*sizeofFloat))
func (w *GameWindow) SetPaddle(paddle *gl_objects.Box) {
w.Paddle = paddle
}
texCoordAttrib := uint32(gl.GetAttribLocation(glProgram, gl.Str("vertTexCoord\x00")))
gl.EnableVertexAttribArray(texCoordAttrib)
gl.VertexAttribPointerWithOffset(texCoordAttrib, 2, gl.FLOAT, false, stride, uintptr(6*sizeofFloat))
func (w *GameWindow) SetCamera(camera *gl_objects.Camera) {
w.Camera = camera
}
textureOnUniform := gl.GetUniformLocation(glProgram, gl.Str("textureOn\x00"))
if textureOn {
gl.Uniform1i(textureOnUniform, 1)
} else {
gl.Uniform1i(textureOnUniform, 0)
func (w *GameWindow) ToggleWireframe() {
// var wg sync.WaitGroup
// for _, o := range w.GLObjects {
// wg.Add(1)
// go func() {
// o.ToggleWireframe()
// wg.Done()
// }()
// }
// wg.Wait()
for _, o := range w.GLObjects {
o.ToggleWireframe()
}
w.wireframe = !w.wireframe
}
func (w *GameWindow) Draw() {
// Probably can't do concurrent drawing due to OpenGL
for _, o := range w.GLObjects {
o.Draw()
}
}
func (w *GameWindow) Update() {
// TODO figure out concurrency
// TODO add lighting eventually
// var wg sync.WaitGroup
// for _, o := range w.GLObjects {
// wg.Add(1)
// go func() {
// o.Update()
// wg.Done()
// }()
// }
// wg.Wait()
for _, o := range w.GLObjects {
o.Update()
}
}

View File

@ -1,6 +1,8 @@
package gl_objects
import (
"log"
gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32"
@ -19,18 +21,20 @@ type Box struct {
GLVertexArrayId uint32
GLVertexBufferId uint32
GLTextureId uint32
Wireframe bool
}
func NewBox(
depth, width, height float32,
width, height, depth float32,
position, color mgl32.Vec3) *Box {
// depth = z axis (towards)
// width = x axis (right)
// height = y axis (up)
box := Box{}
box.Color = color
box.Size = 6
box := Box{
Color: color,
Size: 6,
}
topPos := mgl32.Vec3{position.X(), position.Y() + height/2.0, position.Z()}
top := NewFace(width, depth, topPos, mgl32.Vec3{0, 1, 0}, color)
@ -93,8 +97,11 @@ func (b *Box) Draw() {
// Apply translation
// TODO
//b.drawTriangles()
b.drawOutline()
if b.Wireframe {
b.drawOutline()
} else {
b.drawTriangles()
}
}
func (b *Box) drawTriangles() {
@ -141,3 +148,8 @@ func (b *Box) GetVertexArray() []float32 {
return a
}
func (b *Box) ToggleWireframe() {
log.Println("Wireframe toggled: ", b.Wireframe)
b.Wireframe = !b.Wireframe
}

View File

@ -27,17 +27,18 @@ type Camera struct {
GLProgram uint32
}
func NewCamera(glProgram uint32) Camera {
camera := Camera{}
camera.Up = mgl32.Vec3{0, 1, 0}
camera.OriginalUp = mgl32.Vec3{0, 1, 0}
camera.Direction = mgl32.Vec3{0, 0, -1}
camera.OriginalDirection = mgl32.Vec3{0, 0, -1}
camera.MoveStep = 0.1
camera.RotateStep = 0.01
camera.MouseSensitivity = 0.06
camera.GLProgram = glProgram
return camera
func NewCamera(glProgram uint32) *Camera {
camera := Camera{
Up: mgl32.Vec3{0, 1, 0},
OriginalUp: mgl32.Vec3{0, 1, 0},
Direction: mgl32.Vec3{0, 0, -1},
OriginalDirection: mgl32.Vec3{0, 0, -1},
MoveStep: 0.1,
RotateStep: 0.01,
MouseSensitivity: 0.06,
GLProgram: glProgram,
}
return &camera
}
func (c *Camera) GetCenter() mgl32.Vec3 {
@ -55,6 +56,10 @@ func (c *Camera) Update() {
c.Move(c.Velocity)
}
func (c *Camera) ToggleWireframe() {
return
}
func (c *Camera) Rotate(mouseX, mouseY int32, velocity float32) {
angle := mgl32.Vec3{}
// X Rotation (pitch) - mouse up/down

View File

@ -23,7 +23,7 @@ func NewFace(
center, normal mgl32.Vec3,
color mgl32.Vec3) *Face {
faceColor := mgl32.Vec3{1, 1, 1}
faceColor := color
// top left, shared
v1 := newFaceVertex(
@ -66,12 +66,11 @@ func NewFace(
t1 := NewTriangle(v1, v2, v3)
t2 := NewTriangle(&v3_2, v4, &v1_2)
face := Face{}
face.Triangles = []*Triangle{t1, t2}
face.LineLoopColor = color
face := Face{
Triangles: []*Triangle{t1, t2},
LineLoopColor: color,
}
face.LineLoopVertexArray = face.GetLineLoopVertexArray()
return &face
}
@ -83,10 +82,8 @@ func newFaceVertex(
// {0, 1, 0} and then rotate all the points to fit the actual
// normal.
// Create the vertex offset from the center
v := mgl32.Vec3{center.X() + xoffset, center.Y(), center.Z() + zoffset}
// Subtract the center to create a vector pointing out so we can rotate it
v = v.Sub(center)
// Create the vertex offset from zero
v := mgl32.Vec3{xoffset, 0, zoffset}
up := mgl32.Vec3{0, 1, 0}
angle, err := math_helpers.AngleBetweenVectors(up, normal)
@ -100,7 +97,7 @@ func newFaceVertex(
quat := mgl32.QuatRotate(angle, rotationAxis)
v = quat.Rotate(v)
// add back the center so we get the correct absolute position
// add the center so we get the correct absolute position
v = v.Add(center)
vertex := NewVertex(
@ -146,8 +143,6 @@ func (f *Face) GetLineLoopVertexArray() []float32 {
}
func (f *Face) DrawLineLoop(glProgram uint32) {
gl.LineWidth(5.0)
gl.BindVertexArray(f.GLLineLoopVertexArrayId)
gl.BindBuffer(gl.ARRAY_BUFFER, f.GLLineLoopVertexBufferId)

View File

@ -1,6 +1,7 @@
package gl_objects
type globject interface {
type GLObject interface {
Update()
Draw(uint32)
Draw()
ToggleWireframe()
}

View File

@ -7,8 +7,9 @@ type Triangle struct {
}
func NewTriangle(a, b, c *Vertex) *Triangle {
triangle := Triangle{}
triangle.Vertices = []*Vertex{a, b, c}
triangle := Triangle{
Vertices: []*Vertex{a, b, c},
}
return &triangle
}

View File

@ -13,10 +13,11 @@ type Vertex struct {
}
func NewVertex(x, y, z, r, g, b, u, v float32) *Vertex {
vertex := Vertex{}
vertex.Position = mgl32.Vec3{x, y, z}
vertex.Color = mgl32.Vec3{r, g, b}
vertex.Texture = mgl32.Vec2{u, v}
vertex := Vertex{
Position: mgl32.Vec3{x, y, z},
Color: mgl32.Vec3{r, g, b},
Texture: mgl32.Vec2{u, v},
}
return &vertex
}