我是靠谱客的博主 专一大山,最近开发中收集的这篇文章主要介绍Golang 简单的碰撞检测游戏(ebiten),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这里插入图片描述

简单的碰撞检测游戏

游戏功能:
1、空格键发射红色块,红色块遇到左、右、上边界反弹,遇到下边界游戏结束。
2、左右键移动白色块接红色块,每接到一次加一分。
3、每5秒钟随机生成一个黄色块,红色块触碰到黄色块时,黄色块消失并加十分,黄色块同时最多存在5个

逛博客时看到了一个golang的2D游戏框架ebiten,所以写了个简单游戏来熟悉ebiten流程。
源码地址

main.go

package main

import (
	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/vua/vGame/component"
	"image/color"
	"log"
	"math/rand"
	"time"
)

// Game implements ebiten.Game interface.
type Game struct {
	recv   *component.Square   //白色块
	ball   *component.Square   //红色块
	awards []*component.Square //黄色块
	cls    chan int       
	w      int                  
	h      int
}

// Update proceeds the game state.
// Update is called every tick (1/60 [s] by default).
var a byte = 0xff

func (g *Game) Update() error {
	//发射红色块
	if ebiten.IsKeyPressed(ebiten.KeySpace) {
		g.ball.IsRun = true
	}
	//红色块已发射
	if g.ball.IsRun {
		//边界碰撞检测
		g.ball.CollisionDetection(g.recv, float64(g.w), float64(g.h))
		//吃黄块
		g.ball.HitDetection(&g.awards)
	}
	//左右移动白色块
	if ebiten.IsKeyPressed(ebiten.KeyLeft) {
		g.recv.Move(g.w, -5, g.ball)
	}
	if ebiten.IsKeyPressed(ebiten.KeyRight) {
		g.recv.Move(g.w, 5, g.ball)
	}
	/*if !g.ball.IsAlive() {
		close(g.cls)
		return errors.New("Game Over")
	}*/
	return nil
}

// Draw draws the game screen.
// Draw is called every frame (typically 1/60[s] for 60Hz display).
func (g *Game) Draw(screen *ebiten.Image) {
	//绘制白色块
	screen.DrawImage(g.recv.Image, g.recv.Opts)
	//绘制红色块
	screen.DrawImage(g.ball.Image, g.ball.Opts)
	//绘制黄色块
	for _, i := range g.awards {
		screen.DrawImage(i.Image, i.Opts)
	}
	//红色块落地
	if !g.ball.IsAlive() {
		ebitenutil.DebugPrint(screen, "Game Over")
	} else {
	//显示当前分数
		ebitenutil.DebugPrint(screen, "Score:"+g.ball.GetScore())
	}
	// Write your game's rendering.
}

// Layout takes the outside size (e.g., the window size) and returns the (logical) screen size.
// If you don't have to adjust the screen size with the outside size, just return a fixed size.
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
	return g.w, g.h
}
//每5秒生成一个黄色块
func (g *Game) awardGenerator() {
	ticker := time.NewTicker(5 * time.Second)
	for {
		select {
		case <-ticker.C:
			if !g.ball.IsAlive() {
				return
			}
			if len(g.awards) == 5 {
				g.awards = g.awards[1:5]
			}
			g.awards = append(g.awards, component.NewSquare(Yellow, 5, 5, float64(rand.Intn(300)+10), float64(rand.Intn(200)+10), 0))
		case <-g.cls:
			return
		}
	}
}

var (
	Red    = color.RGBA{0xff, 0x00, 0x00, 0xff}
	Yellow = color.RGBA{0xff, 0xff, 0x00, 0xff}
	White  = color.RGBA{0xff, 0xff, 0xff, 0xff}
)

func main() {
	game := &Game{
		recv:   component.NewSquare(White, 5, 40, 140, 230, 0),
		ball:   component.NewSquare(Red, 5, 5, 157.5, 225, 3),
		awards: make([]*component.Square, 0),
		cls:    make(chan int, 0),
		w:      320,
		h:      240,
	}
	//启动黄色块生成器
	go game.awardGenerator()
	// Specify the window size as you like. Here, a doubled size is specified.
	ebiten.SetWindowSize(640, 480)
	ebiten.SetWindowTitle("vGame")
	// Call ebiten.RunGame to start your game loop.
	if err := ebiten.RunGame(game); err != nil {
		log.Fatal(err)
	}
}

square.go

package component

import (
	"github.com/hajimehoshi/ebiten/v2"
	"image/color"
	"math"
	"math/rand"
	"strconv"
)

type Square struct {
	bgc   color.RGBA   //颜色
	h     float64      //高
	w     float64      //宽
	x     float64      //左上点X坐标
	y     float64      //左上点Y坐标
	step  float64      //移动速度(专用于红色块)
	angle float64      //发射角度(专用于红色块)
	stepX float64      //X方向移动速度(专用于红色块)
	stepY float64      //Y方向移动速度(专用于红色块)
	score int          //得分(专用于红色块)
	alive bool         //是否落地(专用于红色块)
	IsRun bool         //是否已发射(专用于红色块)
	Image *ebiten.Image    //ebiten图像(色块)对象
	Opts  *ebiten.DrawImageOptions    //主要用来控制色块位置
}

func NewSquare(bgc color.RGBA, h, w int, x, y, step float64) *Square {
	image := ebiten.NewImage(w, h)  //创建色块块
	image.Fill(bgc)                 //上色
	opts := &ebiten.DrawImageOptions{}   
	opts.GeoM.Translate(x, y)       //移动到初始位置
	angle := float64(rand.Intn(120) + 30)   //设置初始发射角度
	return &Square{
		bgc:   bgc,
		h:     float64(h),
		w:     float64(w),
		x:     x,
		y:     y,
		step:  step,
		angle: angle,
		stepX: step * math.Cos(angle),   //根据角度和速度计算X,Y方向速度
		stepY: -step * math.Sin(angle),
		alive: true,
		Image: image,
		Opts:  opts,
	}
}
//获取得分(专用于红色块)
func (s *Square) GetScore() string{  
	return strconv.Itoa(s.score)
}
//是否落地(专用于红色块)
func (s *Square) IsAlive() bool{
	return s.alive
}
//边界碰撞检测(专用于红色块)
func (s *Square) CollisionDetection(recv *Square,w,h float64) {
	x, y := s.x+s.stepX, s.y+s.stepY
	tx,ty:=s.stepX,s.stepY
	//碰撞垂直边 (-stepX,stepY)
	//碰撞水平边 (stepX,-stepY)
	if x<=0 {
		tx=-s.x
		ty=tx*math.Tan(s.angle)
		s.stepX*=-1
	} else if x+s.w>=w{
		tx=320-s.w-s.x
		ty=tx*math.Tan(s.angle)
		s.stepX*=-1
	}else if y<=0 {
		ty=-s.y
		tx=ty/math.Tan(s.angle)
		s.stepY*=-1
	}else if y+s.h >= recv.y&& y<= recv.y+recv.h&& x <= recv.w+recv.x && x+s.w >= recv.x {
		s.score++
		ty=recv.y-s.y-s.w
		tx=ty/math.Tan(s.angle)
		if s.stepY*s.stepX<0 {
			tx*=-1
		}
		s.stepY*=-1
	}else if y+s.h>=h {
		s.alive=false
		return
	}
	s.x+=tx
	s.y+=ty
	s.Opts.GeoM.Translate(tx, ty)
}
//与黄色块的碰撞检测(专用于红色块)
func (s *Square) HitDetection(awards *[]*Square){
	for i:=0;i<len(*awards);i++{
		award:=(*awards)[i]
		if math.Abs(s.x-award.x)<=s.w&&math.Abs(s.y-award.y)<=s.h {
			*awards=append((*awards)[0:i],(*awards)[i+1:]...)
			i--
			s.score+=10
		}
	}
}
//左右移动(用于白色块,和未发射的红色块)
func (s *Square) Move(w int,step float64,boll *Square) {
	W:=float64(w)
	if s.x+step < 0 {
		s.Opts.GeoM.Translate(0-s.x, 0)
		if !boll.IsRun{
			boll.Opts.GeoM.Translate(0-s.x, 0)
			boll.x+=-s.x
		}
		s.x = 0
		return
	}
	if s.x+step > W-s.w {
		s.Opts.GeoM.Translate(W-s.w-s.x, 0)
		if !boll.IsRun{
			boll.Opts.GeoM.Translate(W-s.w-s.x, 0)
			boll.x+=W-s.w-s.x
		}
		s.x = W - s.w
		return
	}
	s.x += step
	s.Opts.GeoM.Translate(step, 0)
	if !boll.IsRun {
		boll.Opts.GeoM.Translate(step, 0)
		boll.x+=step
	}
}

最后

以上就是专一大山为你收集整理的Golang 简单的碰撞检测游戏(ebiten)的全部内容,希望文章能够帮你解决Golang 简单的碰撞检测游戏(ebiten)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部