func initSDL() { err := sdl.Init(sdl.INIT_VIDEO) ck(err) wflag := sdl.WINDOW_RESIZABLE if *fullscreen { wflag |= sdl.WINDOW_FULLSCREEN_DESKTOP } screen = newDisplay(W, H, wflag) screen.SetTitle("XSnake 2D") screen.SetLogicalSize(W, H) sdl.ShowCursor(0) }
func main() { runtime.LockOSThread() var fullscreen bool flag.Usage = usage flag.Float64Var(&v0, "v", v0, "maximum start velocity") flag.Float64Var(&xmin, "x", xmin, "left boundary") flag.Float64Var(&xmax, "X", xmax, "right boundary") flag.Float64Var(&ymin, "y", ymin, "top boundary") flag.Float64Var(&ymax, "Y", ymax, "bottom boundary") flag.Float64Var(&dt, "t", dt, "time step") flag.IntVar(&refresh, "F", refresh, "clear every number of frames (0: off)") flag.IntVar(&N, "N", N, "number of particles") flag.IntVar(&size, "s", size, "size of particle (number of pixels)") flag.BoolVar(&fullscreen, "fs", false, "fullscreen") flag.Parse() A = make([]Particle, N) B = make([]Particle, N) prev = A cur = B rand.Seed(time.Now().UnixNano()) err := sdl.Init(sdl.INIT_VIDEO) ck(err) wflag := sdl.WINDOW_RESIZABLE if fullscreen { wflag |= sdl.WINDOW_FULLSCREEN_DESKTOP } screen = NewDisplay(640, 480, wflag) screen.SetDrawColor(White) screen.Clear() screen.Present() screen.SetTitle("Molecular Dynamics") sdl.ShowCursor(0) i := 0 reset() for { sw, sh := screen.Size() viewport.W = int32(sw) viewport.H = int32(sh) if refresh != 0 { if i++; i == refresh { draw(viewport, White) i = 0 } } for i := range cur { cur[i] = Particle{} } for n := 0; n < N; n++ { p := &prev[n] for m := 0; m < n; m++ { q := &prev[m] dx1 := math.Abs(p.x - q.x) dx2 := xmax - xmin - dx1 dx := min(dx1, dx2) dy1 := math.Abs(p.y - q.y) dy2 := ymax - ymin - dy1 dy := min(dy1, dy2) R := dx*dx + dy*dy if R >= 9 || R == 0 { continue } R = 1 / math.Sqrt(R) R2 := R * R R4 := R2 * R2 R6 := R4 * R2 R12 := R6 * R6 F := 24 * (2*R12 - R6) if p.x < q.x { dx = -dx } if p.y < q.y { dy = -dy } if dx1 > dx2 { dx = -dx } if dy1 > dy2 { dy = -dy } dx *= F dy *= F cur[n].ax += dx cur[n].ay += dy cur[m].ax -= dx cur[m].ay -= dy } } for j := 0; j < N; j++ { p := &prev[j] q := &cur[j] q.x = 2*p.x - p.prevx + q.ax*dt*dt q.y = 2*p.y - p.prevy + q.ay*dt*dt q.vx = (q.x - p.prevx) / (2 * dt) q.vy = (q.y - p.prevy) / (2 * dt) q.prevx = p.x q.prevy = p.y if q.x > xmax { q.x -= xmax - xmin q.prevx -= xmax - xmin } if q.x < xmin { q.x += xmax - xmin q.prevx += xmax - xmin } if q.y > ymax { q.y -= ymax - ymin q.prevy -= ymax - ymin } if q.y < ymin { q.y += ymax - ymin q.prevy += ymax - ymin } q.col = p.col x := float64(viewport.W)*(q.x-xmin)/(xmax-xmin) + float64(viewport.X) y := float64(viewport.H)*(q.y-ymin)/(ymax-ymin) + float64(viewport.Y) draw(sdl.Rect{int32(x), int32(y), int32(size), int32(size)}, p.col) } prev, cur = cur, prev screen.Present() for { ev := sdl.PollEvent() if ev == nil { break } switch ev := ev.(type) { case sdl.QuitEvent: os.Exit(0) case sdl.KeyDownEvent: switch ev.Sym { case sdl.K_q, sdl.K_ESCAPE: os.Exit(0) case sdl.K_r: reset() case sdl.K_f: draw(viewport, White) } case sdl.WindowEvent: switch ev.Event { case sdl.WINDOWEVENT_EXPOSED: draw(viewport, White) case sdl.WINDOWEVENT_RESIZED: sw, sh := screen.Size() viewport.W, viewport.H = int32(sw), int32(sh) draw(viewport, White) } } } } }