From 708e70bf45068f4f2ed0c151b407c371838b1e8e Mon Sep 17 00:00:00 2001 From: KalebHawkins Date: Sun, 23 Jun 2024 22:55:29 -0500 Subject: [PATCH] add drawing game loop --- assets/ball.png | Bin 0 -> 2033 bytes assets/embed.go | 8 +++- assets/paddle.png | Bin 0 -> 1986 bytes docs/GameObjects.md | 5 ++- pong/ball.go | 9 ++++ pong/paddle.go | 10 +++++ pong/pong.go | 98 +++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 assets/ball.png create mode 100644 assets/paddle.png create mode 100644 pong/ball.go create mode 100644 pong/paddle.go diff --git a/assets/ball.png b/assets/ball.png new file mode 100644 index 0000000000000000000000000000000000000000..ac2dba8259cffc107e6854ae5b189fae8c6b500b GIT binary patch literal 2033 zcma)74@?th6fZhqGIfHE86{8;M53eD7Fy}qg3|J*taZ>9g$)Krd$b2_@3=eKQqdtO z69v?5lHedNI@BR^8iP*VhGA0|3}PTCI*0QQjx8IqAwiwSeb-_^nPy3^?f3nD@4esq zzW3f$rmRYw={w(-!{N+SCMh)FcQ*UH>J7ewho7Jv&NM$+MmOVHJ*nyI;fX9a?l1UT65VVPSfr$s6WQaNN@f@BB z!y=RD44(G_I*UxAgR@qvU!H}<@=PK$6K?|tF?OiW2zr_~tt%!mScB0-5v9lCZJ3n_ zah(N-hR7)lWiSPJWRQ?AjEdlkBZQGUp#Tv?gHHrs#OHg+YQli$75^t$f6 zl!pOj(Er2t95}+V-J(EgzEsh;jhrwO6c7h;h;)e^hm>-83Pt4MW`NO}#5k@pUM?0$ z#2`zaz{O?n4N1Wrm^od6TQDmPYD@+R#Ls~lF92P!wV<^?0JlT-W)Yc(jxT}S@Tvs6>sGe0IgGh=n6zMU8O9XJ|Mrk6Cv7;2W(gE}ZAcxxe6(b6w2wYH znn@;f<)1w;zf>jO|KZ}PeGdl8E@$nju)RBUao>Roae(i%FHD3zy4lff>}e_)%s!Z1 zvtUVd{-(qaa$}6D)LQChRKfdD6O0Rjggnhgm zjj=Yc`9P^ysf(^|=oTbTO`W^x1`);&k6e1Vnzy35fd9(16{HVzHT^g5KQb#C${KQT ztgCnPYlnOCf<9700dtDxsgmw|b^Qa!HJbQ5p*DZ-wplhmed)qO!@smVjA_~|s39vy zoI_Q97YcX!bYCy6E7@8u$!%DB@9&(eWub*tA1}g8A#?THQfsgNFkD7-?mca54(x3b zhDKNI?6xK^Zr2dKrg=kt2X$9A?p}nq^H*EbwcdcOx%Bn1J()TC)2hB*TvrSV9E!^+`xjQu(!2lw literal 0 HcmV?d00001 diff --git a/assets/embed.go b/assets/embed.go index cdaf2cb..93dcefc 100644 --- a/assets/embed.go +++ b/assets/embed.go @@ -9,5 +9,11 @@ var ( EmpireStateNF_ttf []byte //go:embed background.png - Background []byte + Background_png []byte + + //go:embed paddle.png + Paddle_png []byte + + //go:embed ball.png + Ball_png []byte ) diff --git a/assets/paddle.png b/assets/paddle.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c760792111702bc4ad2b03e8a70ffd6de535dd GIT binary patch literal 1986 zcma)7eM}Q)96nJ{s^Ub4PMO}yf=1U~KPZ%2O9w37z?`-%Or^LYb3$K;<5F~mgX)0w)4F$M`a*7EnRRP3) zryJr3qSE-?gk>#Y(F$NAU25T?-z&vxou2{@)UNhT3Bi@qFRaus6wm|ON1E$R7G1W@giN$ zs4-lrg?5&8;~3`i`NTfCn4)c%G(9~XlgKccOavJsrpm<j=M#l6Y_=CRVzjAGB=op$##H47SP@_-4{ZV2Uf^Pr z_+G$hxRwS43v}>N3uO{nib#?wlF3cd6kMjnQXRt3ZmgHW}N-020lxym8OAHrdSHw=fM(^(YA^7E*d~-s^^L$!&qCrd__1P-@&?rJZ`G_2ay_FY^9m35}JsrPLA z?RZ~ue1CP+)`m$l?}MJH<)Tvy|JYwA zUo2|46$dI-cJ#bBu;pOf+&e_!)(uyewsvK)lhWFfV&V%VCnwGNx7SE{f7|}{L;gEc z#LK3hIoduvL@8Ue_g0tP+|c*_o*A9z{))L2Oq`<(p48caYQv4VPI>jj=G>D0to%kZ P_vzJVFV`K)T3z!G#+tM- literal 0 HcmV?d00001 diff --git a/docs/GameObjects.md b/docs/GameObjects.md index 45c036d..0ae1a96 100644 --- a/docs/GameObjects.md +++ b/docs/GameObjects.md @@ -18,6 +18,7 @@ classDiagram + Run() error + Reset() + drawMainMenu(screen *ebiten.Image) + + drawGameLoop(screen *ebiten.Image) } class Cfg { @@ -25,7 +26,9 @@ classDiagram + screenHeight int + WindowTitle string + faceSource *text.GoTextFaceSource - + background *ebiten.Image + + backgroundImage *ebiten.Image + + paddleImage *ebiten.Image + + ballImage *ebiten.Image } class paddle { diff --git a/pong/ball.go b/pong/ball.go new file mode 100644 index 0000000..d5cf056 --- /dev/null +++ b/pong/ball.go @@ -0,0 +1,9 @@ +package pong + +import "github.com/hajimehoshi/ebiten/v2" + +type ball struct { + x, y int + dx, dy int + sprite *ebiten.Image +} diff --git a/pong/paddle.go b/pong/paddle.go new file mode 100644 index 0000000..58aecf1 --- /dev/null +++ b/pong/paddle.go @@ -0,0 +1,10 @@ +package pong + +import "github.com/hajimehoshi/ebiten/v2" + +type paddle struct { + x, y int + dx int + score int + sprite *ebiten.Image +} diff --git a/pong/pong.go b/pong/pong.go index 78bebba..88ce5dd 100644 --- a/pong/pong.go +++ b/pong/pong.go @@ -7,6 +7,7 @@ import ( "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" + "github.com/hajimehoshi/ebiten/v2/inpututil" "github.com/hajimehoshi/ebiten/v2/text/v2" "gtihub.com/KalebHawkins/pong/assets" ) @@ -14,12 +15,17 @@ import ( const ( fontSize = 48 titleFontSize = fontSize * 1.5 + paddleWidth = 20 ) // Game is a structure containing the game data and configuration. type Game struct { *Cfg state + + playerOne paddle + playerTwo paddle + ball } // Cfg contains the Game's configuration data. @@ -34,6 +40,15 @@ type Cfg struct { faceSource *text.GoTextFaceSource // backgroundImage is the background image backgroundImage *ebiten.Image + // paddleImage is the image used for the paddle + paddleImage *ebiten.Image + // ballImage is the image used for the ball + ballImage *ebiten.Image + + // verticalLine is used as the central delimiter of the screen vertically.. + verticalLine *ebiten.Image + // horizontalLine is used as the central delimiter of the screen horizontally. + horizontalLine *ebiten.Image } // NewGame returns a Game instance to be ran. @@ -43,17 +58,52 @@ func NewGame(cfg *Cfg) *Game { panic(fmt.Sprintf("failed to load font file: %v", err)) } - bgImg, _, err := ebitenutil.NewImageFromReader(bytes.NewReader(assets.Background)) + bgImg, _, err := ebitenutil.NewImageFromReader(bytes.NewReader(assets.Background_png)) if err != nil { panic(fmt.Sprintf("failed to background texture: %v", err)) } + paddleImg, _, err := ebitenutil.NewImageFromReader(bytes.NewReader(assets.Paddle_png)) + if err != nil { + panic(fmt.Sprintf("failed to load paddle texture: %v", err)) + } + + ballImg, _, err := ebitenutil.NewImageFromReader(bytes.NewReader(assets.Ball_png)) + if err != nil { + panic(fmt.Sprintf("failed to load ball texture: %v", err)) + } + cfg.faceSource = fs cfg.backgroundImage = bgImg + cfg.paddleImage = paddleImg + cfg.ballImage = ballImg + cfg.verticalLine = ebiten.NewImage(1, cfg.ScreenHeight) + cfg.horizontalLine = ebiten.NewImage(cfg.ScreenWidth, 1) return &Game{ Cfg: cfg, - state: mainMenu, + state: gameLoop, + playerOne: paddle{ + x: 10 + paddleWidth/2, + y: cfg.ScreenHeight / 2, + dx: 0, + score: 0, + sprite: ebiten.NewImageFromImage(cfg.paddleImage), + }, + playerTwo: paddle{ + x: cfg.ScreenWidth - paddleWidth/2 - 10, + y: cfg.ScreenHeight / 2, + dx: 0, + score: 0, + sprite: ebiten.NewImageFromImage(cfg.paddleImage), + }, + ball: ball{ + x: cfg.ScreenWidth / 2, + y: cfg.ScreenHeight / 2, + dx: 0, + dy: 0, + sprite: ebiten.NewImageFromImage(cfg.ballImage), + }, } } @@ -61,6 +111,10 @@ func NewGame(cfg *Cfg) *Game { func (g *Game) Update() error { switch g.state { case mainMenu: + if inpututil.IsKeyJustPressed(ebiten.KeyEnter) { + g.state = gameLoop + } + case gameLoop: } @@ -69,10 +123,29 @@ func (g *Game) Update() error { // Draw draws the appropriate images to the screen based on game state. func (g *Game) Draw(screen *ebiten.Image) { + imgOpts := &ebiten.DrawImageOptions{} + imgOpts.GeoM.Scale(3, 2) + screen.DrawImage(g.backgroundImage, imgOpts) + + op := &ebiten.DrawImageOptions{} + g.Cfg.verticalLine.Fill(color.White) + op.GeoM.Translate(-float64(g.Cfg.verticalLine.Bounds().Dx())/2, 0) + op.GeoM.Translate(float64(g.Cfg.ScreenWidth/2), 0) + screen.DrawImage(g.Cfg.verticalLine, op) + + op = &ebiten.DrawImageOptions{} + g.Cfg.horizontalLine.Fill(color.White) + op.GeoM.Translate(0, -float64(g.Cfg.horizontalLine.Bounds().Dy()/2)) + op.GeoM.Translate(0, float64(g.Cfg.ScreenHeight)/2) + screen.DrawImage(g.Cfg.horizontalLine, op) + switch g.state { case mainMenu: g.drawMainMenu(screen) + case gameLoop: + g.drawGameLoop(screen) } + } // Layout returns the screen's logical width and height. @@ -89,10 +162,6 @@ func (g *Game) Run() error { } func (g *Game) drawMainMenu(screen *ebiten.Image) { - imgOpts := &ebiten.DrawImageOptions{} - imgOpts.GeoM.Scale(3, 2) - screen.DrawImage(g.backgroundImage, imgOpts) - titleTextFace := &text.GoTextFace{ Source: g.Cfg.faceSource, Size: titleFontSize, @@ -116,3 +185,20 @@ func (g *Game) drawMainMenu(screen *ebiten.Image) { opts.ColorScale.ScaleWithColor(color.Black) text.Draw(screen, "Single Player\nMultiplayer", menuTextFace, opts) } + +func (g *Game) drawGameLoop(screen *ebiten.Image) { + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(-float64(g.playerOne.sprite.Bounds().Dx())/2, -float64(g.playerOne.sprite.Bounds().Dy())/2) + op.GeoM.Translate(float64(g.playerOne.x), float64(g.playerOne.y)) + screen.DrawImage(g.playerOne.sprite, op) + + op = &ebiten.DrawImageOptions{} + op.GeoM.Translate(-float64(g.playerTwo.sprite.Bounds().Dx())/2, -float64(g.playerTwo.sprite.Bounds().Dy())/2) + op.GeoM.Translate(float64(g.playerTwo.x), float64(g.playerTwo.y)) + screen.DrawImage(g.playerTwo.sprite, op) + + op = &ebiten.DrawImageOptions{} + op.GeoM.Translate(-float64(g.ball.sprite.Bounds().Dx())/2, -float64(g.ball.sprite.Bounds().Dy())/2) + op.GeoM.Translate(float64(g.ball.x), float64(g.ball.y)) + screen.DrawImage(g.ball.sprite, op) +}