Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Building a Snake Game With Fyne and Go.
FORCHA
FORCHA

Posted on

     

Building a Snake Game With Fyne and Go.

  1. How to install GO.
  2. How to install fyne.
  3. Drawing Snake and Fruit on Fyne Canvas.
  4. Adding a timer to move the snake.
  5. Using Keys to Control direction.

** 1 How to install Go**
The GO can be downloaded and installed from the official Golang websitehttps://go.dev/doc/install
In this tutorial i will be using a windows environment. I f you are on Mac or Linux please follow the tutorial given on the officialgolang docs

2 How to install Fyne
2.1. For those on Windows environments download and install theGCC compiler. If you are running on a different OS you need to follow this guideFyne Getting Started.

2.2 Using command Line create directory myapp

mkdir myapp && cd myapp
Enter fullscreen modeExit fullscreen mode

2.3. In myapp directory Run the following command and replace MODULE_NAME with your preferred module name (this should be called in a new folder specific for your application).

go mod init MODULE_NAME
Enter fullscreen modeExit fullscreen mode

2.4. You now need to download the Fyne module. This will be done using the following command:

go get fyne.io/fyne/v2
Enter fullscreen modeExit fullscreen mode

2.5. To finish your module’s set up, you now need to tidy the module file to correctly reference Fyne as a dependency.

 go mod tidy
Enter fullscreen modeExit fullscreen mode

3 Drawing Snake and Fruit on Fyne Canvas
3.1. Firstly, we will create a setup function that will build the game screen. We will call
this functionsetupGame and create list that we we populate.

3.2 By iterating through a loop of10 elements (i from 0 to 9) and make a new Rectangle for each position. The elements are all created10 x 20 in size and placed one above the other using the Move function. We
will add them all to the segmentslice.

3.3 The return from this method is acontainer with no layout so that we can later use a manual layout for the visual elements:

funcsetupGame()*fyne.Container{fori:=0;i<lenght;i++{seg:=snakePart{9,float32(5+i)}snakeParts=append(snakeParts,seg)r:=canvas.NewRectangle(&color.RGBA{G:0x66,A:0xff})r.Resize(fyne.NewSize(10,20))r.Move(fyne.NewPos(150,float32(500+i*20)))segments=append(segments,r)}head=canvas.NewRectangle(&color.RGBA{G:0x66,A:0xff})head.Resize(fyne.NewSize(10,20))head.Move(fyne.NewPos(snakeParts[0].x*50,snakeParts[0].y*50))fruit=canvas.NewCircle(&color.RGBA{R:0x66,A:0xff})fruit.Resize(fyne.NewSize(10,10))fruitPos=fyne.NewPos(snakeParts[0].x*20,snakeParts[0].y*20)fruit.Move(fruitPos)segments=append(segments,head)segments=append(segments,fruit)c:=fyne.NewContainerWithoutLayout(segments...)returnc}
Enter fullscreen modeExit fullscreen mode

3.4. With the graphical setup code, we can wrap this in the usual application load code, this time passing the result ofsetupGame() to theSetContent function. As this game will not have dynamic sizing, we will callSetFixedSize(true) so that the window cannot be resized

funcmain(){a:=app.New()w:=a.NewWindow("Snake")w.Resize(fyne.NewSize(800,800))w.SetFixedSize(false)game=setupGame()w.SetContent(game)w.Canvas().SetOnTypedKey(keyTyped)gorunGame()w.ShowAndRun()}
Enter fullscreen modeExit fullscreen mode

4. Adding a timer to move the snake
The next step is to add some motion to the game. We will start with a simple timer that
repositions the snake on screen:

4.1. To help manage the game state, we will define a new type to store the x, y value of
each snake segment, namedsnakePart. We then make a slice that contains all of
the elements, and this is what we will update as the snake moves around the screen.

typesnakePartstruct{x,yfloat32}var(snakeParts[]snakePartgame*fyne.Containerhead*canvas.Rectanglefruit*canvas.Circlemove=moveDownsegments[]fyne.CanvasObjectlenghtint=20fruitPosfyne.Position)
Enter fullscreen modeExit fullscreen mode

4.2. We create a new function that will update the rectangles that we created earlier based on updated snake section information. To make sure that the game refreshes each time we move the snake, we need to move the rectangles and call ** Refresh()**.

funcrefreshGame(){fori,seg:=rangesnakeParts{rect:=game.Objects[i]rect.Move(fyne.NewPos(seg.x*10,seg.y*20))}game.Refresh()}
Enter fullscreen modeExit fullscreen mode

4.3. To run the main game loop, we need one more function that will use a timer of250 milliseconds to move the snake. We call this functionrunGame.

4.4. To move the snake forward , we copy the position of each element from that of the element that is one segment further forward, working from the tail to the head.

5. Using keys to control direction
5.1. To start with, we define a new type (moveType) that will be used to describe the
next direction in which to move. The move variable is then defined to hold the next move direction:

typemoveTypeintconst(moveUpmoveType=iotamoveDownmoveLeftmoveRight)varmove=moveUp
Enter fullscreen modeExit fullscreen mode

5.2. Create a new keyTyped function as follows that will perform the keyboard
mapping:

funckeyTyped(e*fyne.KeyEvent){switche.Name{casefyne.KeyUp:move=moveUpcasefyne.KeyDown:move=moveDowncasefyne.KeyLeft:move=moveLeftcasefyne.KeyRight:move=moveRight}}
Enter fullscreen modeExit fullscreen mode

5.3. For the key events to be triggered we use theSetOnKeyTyped() function on the window's canvas.

w.Canvas().SetOnTypedKey(keyTyped)
Enter fullscreen modeExit fullscreen mode

5.4. Lastly, the code moves the head to a new position, in this case further up the screen (by usingsnakeParts[0].y-1). Refer to the following function:

5.5. We set up our animations inside the for loop in the runGame function, before the
timer pause

funcrunGame(){nextPart:=snakePart{snakeParts[0].x,snakeParts[0].y-1}for{oldPos:=fyne.NewPos(snakeParts[0].x*10,snakeParts[0].y*10)newPos:=fyne.NewPos(nextPart.x*10,nextPart.y*10)canvas.NewPositionAnimation(oldPos,newPos,time.Millisecond*250,func(pfyne.Position){head.Move(p)canvas.Refresh(head)}).Start()end:=len(snakeParts)-1canvas.NewPositionAnimation(fyne.NewPos(snakeParts[end].x*10,snakeParts[end].y*10),fyne.NewPos(snakeParts[end-1].x*10,snakeParts[end-1].y*10),time.Millisecond*250,func(pfyne.Position){tail:=game.Objects[end]tail.Move(p)canvas.Refresh(tail)}).Start()time.Sleep(time.Millisecond*250)fori:=len(snakeParts)-1;i>=1;i--{snakeParts[i]=snakeParts[i-1]}snakeParts[0]=nextPart//SetUp the new head positionrefreshGame()}}
Enter fullscreen modeExit fullscreen mode

5.6. After the refresh line, we need to update the movement calculations to set up nextPart ready for the next movement:

switchmove{casemoveUp:nextPart=snakePart{nextPart.x,nextPart.y-1}casemoveDown:nextPart=snakePart{nextPart.x,nextPart.y+1}casemoveLeft:nextPart=snakePart{nextPart.x-1,nextPart.y}casemoveRight:nextPart=snakePart{nextPart.x+1,nextPart.y}}
Enter fullscreen modeExit fullscreen mode

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
karanpratapsingh profile image
Karan Pratap Singh
A software engineer who aims to evolve, innovate, and inspire through technology.

Interesting, thanks for sharing!

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I am Forcha Pearl , a Software Engineer who is passionate in technology.
  • Joined

More fromFORCHA

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp