概述
简单的碰撞检测游戏
游戏功能:
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)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复