Initial commit

master
DustyP 6 years ago
commit 5af07f0aec

@ -0,0 +1,216 @@
package main
import (
"github.com/veandco/go-sdl2/sdl"
"log"
"math"
"math/rand"
"time"
)
var (
winWidth = 800
winHeight = 600
speed = 10
blockSize = 10
random = rand.New(rand.NewSource(time.Now().Unix()))
)
func main() {
err := sdl.Init(sdl.INIT_EVERYTHING)
if err != nil {
log.Fatal(err)
}
defer sdl.Quit()
window, err := sdl.CreateWindow(
"PONG",
sdl.WINDOWPOS_CENTERED,
sdl.WINDOWPOS_CENTERED,
int32(winWidth),
int32(winHeight),
sdl.WINDOW_SHOWN)
if err != nil {
log.Fatal(err)
}
defer window.Destroy()
renderer, err := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
log.Fatal(err)
}
defer renderer.Destroy()
centerX, centerY := getCenter()
snakeRect := sdl.Rect{
X: int32(centerX),
Y: int32(centerY),
W: 10,
H: 10,
}
fruitRect := sdl.Rect{
X: 0,
Y: 0,
W: 10,
H: 10,
}
background, err := renderer.CreateTexture(
sdl.PIXELFORMAT_ABGR8888,
sdl.TEXTUREACCESS_STREAMING,
int32(winWidth),
int32(winHeight))
if err != nil {
log.Fatal(err)
}
defer background.Destroy()
snakeTex, err := renderer.CreateTexture(
sdl.PIXELFORMAT_ABGR8888,
sdl.TEXTUREACCESS_STREAMING,
snakeRect.W,
snakeRect.H)
if err != nil {
log.Fatal(err)
}
defer snakeTex.Destroy()
fruitTex, err := renderer.CreateTexture(
sdl.PIXELFORMAT_ABGR8888,
sdl.TEXTUREACCESS_STREAMING,
fruitRect.W,
fruitRect.H)
if err != nil {
log.Fatal(err)
}
defer fruitTex.Destroy()
fruitPixels := make([]byte, fruitRect.H * fruitRect.W * 4)
for y := 1; y < int(fruitRect.H) - 1; y++ {
for x := 1; x < int(fruitRect.W) - 1; x++ {
i := (y * int(fruitRect.W) + x) * 4
fruitPixels[i] = 255
fruitPixels[i + 1] = 0
fruitPixels[i + 2] = 0
fruitPixels[i + 3] = 255
}
}
fruitTex.Update(nil, fruitPixels, int(fruitRect.W) * 4)
snakePixels := make([]byte, snakeRect.H * snakeRect.W * 4)
for y := 1; y < int(snakeRect.H) - 1; y++ {
for x := 1; x < int(snakeRect.W) - 1; x++ {
i := (y * int(snakeRect.W) + x) * 4
snakePixels[i] = 255
snakePixels[i + 1] = 255
snakePixels[i + 2] = 255
snakePixels[i + 3] = 255
}
}
snakeTex.Update(nil, snakePixels, int(snakeRect.W) * 4)
keyState := sdl.GetKeyboardState()
pixels := make([]byte, winHeight*winWidth*4)
background.Update(nil, pixels, winWidth * 4)
renderer.Copy(background, nil, nil)
snake := &snakeBody{
Rect: snakeRect,
dx: 0,
dy: -snakeRect.H,
tex: snakeTex,
next: nil,
}
fruit := &fruit{
Rect: fruitRect,
tex: fruitTex,
}
fruit.newLoc(snake, winWidth - int(fruit.W), winHeight - int(fruit.H))
snake.draw(renderer)
fruit.draw(renderer)
renderer.Present()
frameStart := time.Now()
for {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
return
}
}
if keyState[sdl.SCANCODE_UP] != 0 {
if snake.canMoveTo(0, -snakeRect.H) {
snake.dy = -snakeRect.H
snake.dx = 0
}
} else if keyState[sdl.SCANCODE_DOWN] != 0 {
if snake.canMoveTo(0, snakeRect.H) {
snake.dy = snakeRect.H
snake.dx = 0
}
} else if keyState[sdl.SCANCODE_RIGHT] != 0 {
if snake.canMoveTo(snakeRect.W, 0) {
snake.dy = 0
snake.dx = snakeRect.W
}
} else if keyState[sdl.SCANCODE_LEFT] != 0 {
if snake.canMoveTo(-snakeRect.W, 0) {
snake.dy = 0
snake.dx = -snakeRect.W
}
}
if time.Since(frameStart).Milliseconds() >= 150 {
renderer.Clear()
renderer.Copy(background, nil, nil)
snake.update()
if snake.detectBodyCollision() || snake.X < 0 || snake.X >= int32(winWidth) || snake.Y < 0 || snake.Y >= int32(winHeight) {
log.Println("Game Over")
break
}
if snake.foundFruit(*fruit) {
log.Println("Found Fruit")
snake.grow()
log.Println("Grown")
fruit.newLoc(snake, winWidth-int(fruit.W), winHeight-int(fruit.H))
log.Println("New Fruit location")
}
snake.draw(renderer)
fruit.draw(renderer)
renderer.Present()
frameStart = time.Now()
}
sdl.Delay(10)
}
}
func isEmpty(rect sdl.Rect, s *snakeBody) bool {
for s != nil {
if rect.X == s.Rect.X && rect.Y == s.Rect.Y {
return false
}
s = s.next
}
return true
}
func getRandomRect(w, h int) sdl.Rect {
randX := int32(random.Intn(w))
randY := int32(random.Intn(h))
return sdl.Rect{
X: round(randX, 10),
Y: round(randY, 10),
}
}
func round(x, unit int32) int32 {
return int32(math.Round(float64(x/unit))) * unit
}
func getCenter() (int, int) {
return winWidth / 2, winHeight / 2
}

@ -0,0 +1,101 @@
package main
import "github.com/veandco/go-sdl2/sdl"
type snakeBody struct {
sdl.Rect
dx int32
dy int32
tex *sdl.Texture
next *snakeBody
}
type fruit struct {
sdl.Rect
tex *sdl.Texture
}
func (s *snakeBody) detectCollision(rect sdl.Rect) bool {
return s.X == rect.X && s.Y == rect.Y
}
func (s *snakeBody) foundFruit(fruit fruit) bool {
return s.detectCollision(fruit.Rect)
}
func (s *snakeBody) detectBodyCollision() bool {
nextChunk := s.next
for nextChunk != nil {
if s.detectCollision(nextChunk.Rect) {
return true
}
nextChunk = nextChunk.next
}
return false
}
func (s *snakeBody) draw(renderer *sdl.Renderer) {
chunk := s
for chunk != nil {
renderer.Copy(chunk.tex, nil, &chunk.Rect)
chunk = chunk.next
}
}
func (s *snakeBody) update() {
prevRect := s.Rect
s.X += s.dx
s.Y += s.dy
next := s.next
for next != nil {
nextRect := next.Rect
next.Rect = prevRect
prevRect = nextRect
next = next.next
}
}
func (s *snakeBody) grow() {
last := s
for {
if last.next == nil {
break
}
last = last.next
}
var newSnake *snakeBody
for i := 0; i < 3; i++ {
newSnake = &snakeBody{
Rect: last.Rect,
dx: 0,
dy: 0,
tex: last.tex,
next: newSnake,
}
}
last.next = newSnake
}
func (s *snakeBody) canMoveTo(dx, dy int32) bool {
if s.next == nil {
return true
}
nextRect := s.next.Rect
if s.X + dx == nextRect.X && s.Y + dy == nextRect.Y {
return false
}
return true
}
func (f *fruit) draw(renderer *sdl.Renderer) {
renderer.Copy(f.tex, nil, &f.Rect)
}
func (f *fruit) newLoc(s *snakeBody, w, h int) {
rect := getRandomRect(w, h)
for !isEmpty(rect, s) {
rect = getRandomRect(w, h)
}
f.X = rect.X
f.Y = rect.Y
}
Loading…
Cancel
Save