2D小游戏-创新设计——《弹射挑战》
推荐使用Go语言的ebiten
库来开发一个2D小游戏。下面是一个创新设计——《弹射挑战》的代码示例,包含等级、物理弹射、随机地形和本地排行榜功能。
package main
import (
"encoding/json"
"image/color"
"log"
"math"
"math/rand"
"os"
"sort"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/inpututil"
)
const (
screenWidth = 800
screenHeight = 600
gravity = 0.5
)
type Player struct {
X, Y float64
Angle float64
Power float64
Score int
Level int
XP int
Upgrades map[string]int
Projectiles []*Projectile
}
type Projectile struct {
X, Y float64
Vx, Vy float64
Active bool
}
type Target struct {
X, Y float64
Value int
}
type Game struct {
Player *Player
Targets []*Target
CurrentLevel int
Launched bool
Ranking []ScoreEntry
ShowRanking bool
UpgradeChoices []string
}
type ScoreEntry struct {
Name string
Score int
Level int
}
func (g *Game) SaveRanking() {
file, _ := json.MarshalIndent(g.Ranking, "", " ")
_ = os.WriteFile("ranking.json", file, 0644)
}
func (g *Game) LoadRanking() {
if file, err := os.ReadFile("ranking.json"); err == nil {
_ = json.Unmarshal(file, &g.Ranking)
}
}
func (g *Game) AddScore(name string, score int, level int) {
g.Ranking = append(g.Ranking, ScoreEntry{Name: name, Score: score, Level: level})
sort.Slice(g.Ranking, func(i, j int) bool {
return g.Ranking[i].Score > g.Ranking[j].Score
})
if len(g.Ranking) > 10 {
g.Ranking = g.Ranking[:10]
}
}
func NewGame() *Game {
g := &Game{
Player: &Player{
X: 100,
Y: screenHeight - 100,
Upgrades: make(map[string]int),
},
CurrentLevel: 1,
}
g.LoadRanking()
g.GenerateLevel()
return g
}
func (g *Game) GenerateLevel() {
g.Targets = nil
// 生成随机地形和目标
for i := 0; i < 3+g.CurrentLevel; i++ {
g.Targets = append(g.Targets, &Target{
X: float64(400 + rand.Intn(300)),
Y: float64(200 + rand.Intn(200)),
Value: 100 * g.CurrentLevel,
})
}
}
func (g *Game) fire() {
p := g.Player
radians := p.Angle * math.Pi / 180
power := p.Power * 5
proj := &Projectile{
X: p.X,
Y: p.Y,
Vx: math.Cos(radians) * power,
Vy: math.Sin(radians) * power,
Active: true,
}
p.Projectiles = append(p.Projectiles, proj)
}
func (g *Game) Update() error {
p := g.Player
// 升级选择
if len(g.UpgradeChoices) > 0 {
if inpututil.IsKeyJustPressed(ebiten.Key1) {
p.Upgrades[g.UpgradeChoices[0]]++
g.UpgradeChoices = nil
}
if inpututil.IsKeyJustPressed(ebiten.Key2) {
p.Upgrades[g.UpgradeChoices[1]]++
g.UpgradeChoices = nil
}
return nil
}
// 控制逻辑
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
p.Angle--
}
if ebiten.IsKeyPressed(ebiten.KeyRight) {
p.Angle++
}
if ebiten.IsKeyPressed(ebiten.KeyUp) {
p.Power++
}
if ebiten.IsKeyPressed(ebiten.KeyDown) {
p.Power--
}
if inpututil.IsKeyJustPressed(ebiten.KeySpace) && !g.Launched {
g.fire()
g.Launched = true
}
// 更新弹道
for _, proj := range p.Projectiles {
if proj.Active {
proj.Vy += gravity
proj.X += proj.Vx
proj.Y += proj.Vy
// 碰撞检测
for _, t := range g.Targets {
dx := proj.X - t.X
dy := proj.Y - t.Y
if dx*dx+dy*dy < 400 {
p.Score += t.Value
p.XP += t.Value / 10
t.Value = 0
}
}
if proj.Y > screenHeight-50 {
proj.Active = false
g.Launched = false
}
}
}
// 升级检查
if p.XP >= 1000 {
p.Level++
p.XP -= 1000
g.UpgradeChoices = []string{"Power+", "MultiShot"}
}
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
// 绘制玩家
ebitenutil.DrawCircle(screen, g.Player.X, g.Player.Y, 10, color.RGBA{0, 255, 0, 255})
// 绘制弹道线
radians := g.Player.Angle * math.Pi / 180
endX := g.Player.X + math.Cos(radians)*50
endY := g.Player.Y + math.Sin(radians)*50
ebitenutil.DrawLine(screen, g.Player.X, g.Player.Y, endX, endY, color.White)
// 绘制目标和地形
for _, t := range g.Targets {
if t.Value > 0 {
ebitenutil.DrawCircle(screen, t.X, t.Y, 20, color.RGBA{255, 0, 0, 255})
}
}
// 绘制弹射物
for _, proj := range g.Player.Projectiles {
if proj.Active {
ebitenutil.DrawCircle(screen, proj.X, proj.Y, 5, color.RGBA{255, 255, 0, 255})
}
}
// 显示UI信息
ebitenutil.DebugPrint(screen,
"Score: "+string(g.Player.Score)+
"\nLevel: "+string(g.Player.Level)+
"\nXP: "+string(g.Player.XP)+
"\nAngle: "+string(g.Player.Angle)+
"\nPower: "+string(g.Player.Power))
// 显示升级选项
if len(g.UpgradeChoices) > 0 {
ebitenutil.DebugPrint(screen,
"Choose Upgrade:\n1. "+g.UpgradeChoices[0]+
"\n2. "+g.UpgradeChoices[1])
}
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("弹射挑战")
if err := ebiten.RunGame(NewGame()); err != nil {
log.Fatal(err)
}
}
游戏特色说明:
- 物理弹射系统:通过调整角度和力度进行发射
- 随机生成地形:每个关卡目标位置随机
- RPG升级系统:通过得分积累经验升级
- 技能选择系统:升级时可选择不同强化方向
- 本地排行榜:自动保存前10名成绩
- 渐进难度:关卡越高目标越多
操作方法:
- 方向键←→调整角度
- 方向键↑↓调整力度
- 空格键发射
- 数字键选择升级
扩展建议:
- 添加更多升级选项(弹射数量、特殊能力等)
- 增加障碍物和移动目标
- 添加粒子特效
- 实现网络排行榜
- 增加成就系统
- 添加音效和背景音乐
这个游戏结合了物理弹射、RPG升级和策略选择元素,通过简单的操作提供深度游戏体验。玩家需要不断优化发射策略并选择适合的升级路线来挑战更高分数。