// Render a mandelbrot fractal onto the given sdl surface func Mandelbrot(state *FractalData, screen *sdl.Surface, pal []uint32) { fmt.Println("Beginning Mandelbrot") var wg sync.WaitGroup aspect := state.FractalState.Aspect() xincr, yincr := state.FractalState.Increments() y_cur := imag(state.Center) + (state.Scale/aspect)/2.0 wg.Add(state.Height) for y := 0; y < state.Height; y++ { x_cur := real(state.Center) - state.Scale/2.0 go mandelbrot_row(x_cur, y_cur, xincr, y, state, &wg) y_cur -= yincr } wg.Wait() fmt.Println("Rendering mandelbrot") screen.Lock() defer screen.Unlock() wg.Add(state.Height) offset := uintptr(unsafe.Pointer(screen.Pixels)) delta := uintptr(screen.Pitch / 1) for y := 0; y < state.Height; y++ { go renderRow(offset, y, state, pal, &wg) offset += delta } wg.Wait() //invocations++ fmt.Println("Mandeblrot completed") }
// Draw the given list of Drawables on the surface. Items should be a list of Drawables func draw(screen *sdl.Surface, items *list.List) { screen.FillRect(nil, uint32(0x00202020)) for cur := items.Front(); cur != nil; cur = cur.Next() { if d, ok := cur.Value.(Drawable); ok { d.Draw(screen) } } }
func wrap(cSurface *C.SDL_Surface) *sdl.Surface { var s *sdl.Surface if cSurface != nil { var surface sdl.Surface surface.SetCSurface(unsafe.Pointer(cSurface)) s = &surface } else { s = nil } return s }
// Draw the Goal object on the given surface func (g Goal) Draw(screen *sdl.Surface) { if g.Hidden || g.Surface == nil { return } screen.Blit(g.Rect(), g.Surface, nil) }
//The main loop. Handles drawing, events, ... This should be broken up into a smaller set of functions // if more event logic is handled. func mainLoop(screen *sdl.Surface, markers []Marker, goals []*Goal) { var curGoal int timer := make(chan bool, 0) running := true redraw := true requestRedraw := false stickCount := len(markers) // start the timer go timeLoop(timer) for running { if redraw { items := list.New() nextGoal := false var curRect *sdl.Rect if curGoal >= 0 && curGoal < len(goals) { curRect = goals[curGoal].Rect() } for i := 0; i < stickCount; i++ { markers[i].Update() items.PushBack(markers[i]) if curRect != nil { if markers[i].Intersects(curRect) { nextGoal = true } } } if nextGoal { curGoal++ if curGoal >= len(goals) { curGoal = 0 } } if curGoal >= 0 && curGoal < len(goals) { items.PushBack(goals[curGoal]) } draw(screen, items) screen.Flip() //fmt.Printf(".") redraw = false requestRedraw = false } select { case <-timer: zeroCnt := 0 for _, m := range markers { if m.last2Zero { zeroCnt++ } } if zeroCnt < stickCount || requestRedraw { redraw = true } case _event := <-sdl.Events: switch e := _event.(type) { case sdl.QuitEvent: running = false case sdl.KeyboardEvent: if e.Keysym.Sym == sdl.K_ESCAPE || e.Keysym.Sym == sdl.K_q { running = false } case sdl.JoyAxisEvent: if e.Axis < 2 { val := float32(0.0) if e.Value > 2000 || e.Value < -2000 { val = float32(e.Value) / float32(uint32(0x0ffff)) } //fmt.Println("got joystick axis event ", e) if e.Axis == 0 { markers[e.Which].Vax = val } else { markers[e.Which].Vay = val } requestRedraw = true } case sdl.JoyButtonEvent: if e.State > 0 { markers[e.Which].Big++ } else { markers[e.Which].Big-- } if markers[e.Which].Big < 0 { markers[e.Which].Big = 0 } requestRedraw = true case sdl.JoyHatEvent: switch e.Value { case sdl.HAT_CENTERED: markers[e.Which].Vhx = 0.0 markers[e.Which].Vhy = 0.0 case sdl.HAT_UP: markers[e.Which].Vhx = 0.0 markers[e.Which].Vhy = -1.0 case sdl.HAT_RIGHT: markers[e.Which].Vhx = 1.0 markers[e.Which].Vhy = 0.0 case sdl.HAT_DOWN: markers[e.Which].Vhx = 0.0 markers[e.Which].Vhy = 1.0 case sdl.HAT_LEFT: markers[e.Which].Vhx = -1.0 markers[e.Which].Vhy = 0.0 case sdl.HAT_RIGHTUP: markers[e.Which].Vhx = 1.0 markers[e.Which].Vhy = -1.0 case sdl.HAT_RIGHTDOWN: markers[e.Which].Vhx = 1.0 markers[e.Which].Vhy = 1.0 case sdl.HAT_LEFTUP: markers[e.Which].Vhx = -1.0 markers[e.Which].Vhy = -1.0 case sdl.HAT_LEFTDOWN: markers[e.Which].Vhx = -1.0 markers[e.Which].Vhy = 1.0 } //fmt.Println("Hat event ", e, " (",markers[e.Which].Vhx,",",markers[e.Which].Vhy,")") requestRedraw = true case sdl.ResizeEvent: //println("resize screen ", e.W, e.H) panic("Resize not supported yet") //screen = sdl.SetVideoMode(int(e.W), int(e.H), 32, sdl.RESIZABLE) //if screen == nil { // fmt.Println(sdl.GetError()) //} } } // yeild to allow other activities (such as the timer loop) runtime.Gosched() } }
// draw the marker func (m Marker) Draw(screen *sdl.Surface) { screen.FillRect(m.Rect(), m.Color) }