Go Ebiten小球弹性碰撞代码示例
Go Ebiten小球弹性碰撞代码示例
我们来编写一个简单的示例程序,在其中实现一个小球在窗口中弹性碰撞的效果。具体来说,当小球碰到窗口的边缘时,它会反弹回来,改变运动方向。我们将使用Ebiten的图形和物理模拟功能来实现这个效果。
代码解析
-
结构体定义
Position
用于表示小球的坐标(X和Y)。Velocity
表示小球的速度,包含水平速度Vx
和垂直速度Vy
。Ball
结构体包含了小球的坐标、速度和半径。
-
游戏逻辑 (
Update
方法)
在Update
方法中,我们检查小球是否碰到窗口的边界。如果小球碰到边界(即小球的X或Y坐标超出了边界),我们就反转相应的速度(使得小球反弹回来)。这就是实现弹性碰撞的基本逻辑。if g.B.Pos.X <= g.B.R || g.B.Pos.X >= WindowWidth-g.B.R { g.B.V.Vx = -g.B.V.Vx // 水平方向速度取反,实现弹性碰撞 } if g.B.Pos.Y <= g.B.R || g.B.Pos.Y >= WindowHeight-g.B.R { g.B.V.Vy = -g.B.V.Vy // 垂直方向速度取反,实现弹性碰撞 }
-
绘制小球 (
Draw
方法)
在Draw
方法中,我们使用vector.DrawFilledCircle
方法来绘制小球。小球的颜色是白色的,位置根据小球的坐标来确定。 -
随机初始化
小球的初始位置和速度是通过rand.Float32()
随机生成的,这样每次运行游戏时,都会有不同的效果。
完整代码
package main
import (
"image/color"
"math/rand/v2"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/vector"
)
const (
WindowWidth = 640 // 窗口宽度
WindowHeight = 480 // 窗口高度
ballRadius = 20 // 小球的半径
)
// 定义小球的位置结构体
type Position struct {
X, Y float32 // X 和 Y 坐标
}
// 定义小球的速度结构体
type Velocity struct {
Vx, Vy float32 // X 和 Y 方向的速度
}
// 定义小球结构体
type Ball struct {
Pos Position // 小球的位置
V Velocity // 小球的速度
R float32 // 小球的半径
}
// 游戏主结构体
type Game struct {
B *Ball // 包含一个小球对象
}
// 游戏的逻辑更新函数
func (g *Game) Update() error {
// 检测小球是否碰到左右墙壁
if g.B.Pos.X <= g.B.R || g.B.Pos.X >= WindowWidth-g.B.R {
g.B.V.Vx = -g.B.V.Vx // 水平方向速度取反,实现弹性碰撞
}
// 检测小球是否碰到上下墙壁
if g.B.Pos.Y <= g.B.R || g.B.Pos.Y >= WindowHeight-g.B.R {
g.B.V.Vy = -g.B.V.Vy // 垂直方向速度取反,实现弹性碰撞
}
// 更新小球的位置
g.B.Pos.X += g.B.V.Vx
g.B.Pos.Y += g.B.V.Vy
return nil
}
// 游戏的绘制函数
func (g *Game) Draw(screen *ebiten.Image) {
// 绘制小球,使用白色填充
vector.DrawFilledCircle(screen, g.B.Pos.X, g.B.Pos.Y, g.B.R, color.White, true)
}
// 游戏窗口的布局设置函数
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return outsideWidth, outsideHeight // 返回窗口大小
}
// 主函数
func main() {
// 设置窗口大小
ebiten.SetWindowSize(WindowWidth, WindowHeight)
// 设置窗口标题
ebiten.SetWindowTitle("Ball dome")
// 初始化一个小球
ball := &Ball{
// 随机初始化小球的位置
Position{
X: WindowWidth * rand.Float32(), // 随机X坐标
Y: WindowHeight * rand.Float32(), // 随机Y坐标
},
// 随机初始化小球的速度
Velocity{
Vx: 2 * rand.Float32(), // 随机水平速度
Vy: 2 * rand.Float32(), // 随机垂直速度
},
ballRadius, // 小球半径
}
// 启动游戏
if err := ebiten.RunGame(&Game{ball}); err != nil {
panic(err) // 如果游戏运行错误,输出错误信息
}
}