Go SDL2 Lesson 5

Rectangle Collision Detection

Today is all about collision detection using SDL rectangles. This method does have problems dealing with very rounded images, but it has the benefit of being fast and easy to check if there has been a collision. In this example two filled in boxes (blue and green) are checked to see if they intersect/collide. When they do intersect, a third box (outlined and red) is drawn showing the location of where they collide.

Go SDL2 Lesson 5

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/veandco/go-sdl2/sdl"
)

const (
	screenWidth  = 640
	screenHeight = 480
)

// Globals - terrible for serious programs, great for short examples
var (
	window    *sdl.Window
	renderer  *sdl.Renderer
	event     sdl.Event
	quit      bool
	err       error
	ticker    *time.Ticker
	box1      *sdl.Rect
	box2      *sdl.Rect
	box3      sdl.Rect
	velX      int32
	intersect bool
)

// Setup program
func Setup() (successful bool) {
	err = sdl.Init(sdl.INIT_VIDEO)
	if err != nil {
		fmt.Printf("Failed to initialize sdl: %s\n", err)
		return false
	}
	window, err = sdl.CreateWindow("Go + SDL2 Lesson 5", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		screenWidth, screenHeight, sdl.WINDOW_SHOWN)
	if err != nil {
		fmt.Printf("Failed to create renderer: %s\n", err)
		return false
	}

	renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if err != nil {
		fmt.Printf("Failed to create renderer: %s\n", err)
		return false
	}

	sdl.SetHint(sdl.HINT_RENDER_SCALE_QUALITY, "1")

	box1 = &sdl.Rect{X: (screenWidth / 2) - 50,
		Y: (screenHeight / 2) - 50,
		W: 100, H: 100}

	box2 = &sdl.Rect{X: 0,
		Y: (screenHeight / 2),
		W: 100, H: 100}

	velX = 5

	return true
}

// Shutdown program
func Shutdown() {
	renderer.Destroy()
	window.Destroy()
	sdl.Quit()
}

// HandleEvents input mostly
func HandleEvents() {
	for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
		switch t := event.(type) {
		case *sdl.QuitEvent:
			quit = true
		case *sdl.KeyboardEvent:
			if t.Keysym.Sym == sdl.K_ESCAPE {
				quit = true
			}
		}
	}
}

// Draw to screen
func Draw() {
	//clear the screen
	renderer.SetDrawColor(255, 255, 55, 255)
	renderer.Clear()
	//draw box 1 (blue)
	renderer.SetDrawColor(0, 0, 255, 255)
	renderer.FillRect(box1)
	//draw box 2 (green)
	renderer.SetDrawColor(0, 255, 0, 255)
	renderer.FillRect(box2)
	//if there is a collision between box 1 & 2 then draw a third box (red)
	//where the two boxes intersect
	if intersect {
		renderer.SetDrawColor(255, 0, 0, 255)
		renderer.DrawRect(&box3)
	}
	renderer.Present()
}

func main() {
	if !Setup() {
		os.Exit(1)
	}

	ticker = time.NewTicker(time.Second / 30)

	for !quit {
		HandleEvents()
		Update()
		Draw()
		<-ticker.C // wait up to 1/30th of a second

	}

	Shutdown()
}

// Update program
func Update() {
	box2.X += velX

	if box2.X+100 >= screenWidth {
		velX *= -1
	}
	if box2.X <= 0 {
		velX *= -1
	}

	/* HasIntersection is similar to Intersect except that HasIntersection
	   only returns true/false and does not return a sdl.Rect like Intersect
	   does. This is included, but commented out, for completeness.

	if box1.HasIntersection(box2) {
		fmt.Println("intersection")
	}
	*/

	/*check if box1 intersects with box2 - this function returns a bool
	and a sdl.Rect of the intersection if true
	*/
	box3, intersect = box1.Intersect(box2)
	if intersect {
		fmt.Print("Rectange Collision Detected ")
	}

}

Lesson 5 source code can also be found on Github.

July 31, 2018 Update: Updated code to deal with breaking changes introduced to Go-SDL2 by version 0.3.