2D小游戏-创新设计——《弹射挑战》

推荐使用Go语言的ebiten库来开发一个2D小游戏。下面是一个创新设计------《弹射挑战》的代码示例,包含等级、物理弹射、随机地形和本地排行榜功能。

go 复制代码
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)
	}
}

游戏特色说明:

  1. 物理弹射系统:通过调整角度和力度进行发射
  2. 随机生成地形:每个关卡目标位置随机
  3. RPG升级系统:通过得分积累经验升级
  4. 技能选择系统:升级时可选择不同强化方向
  5. 本地排行榜:自动保存前10名成绩
  6. 渐进难度:关卡越高目标越多

操作方法:

  • 方向键←→调整角度
  • 方向键↑↓调整力度
  • 空格键发射
  • 数字键选择升级

扩展建议:

  1. 添加更多升级选项(弹射数量、特殊能力等)
  2. 增加障碍物和移动目标
  3. 添加粒子特效
  4. 实现网络排行榜
  5. 增加成就系统
  6. 添加音效和背景音乐

这个游戏结合了物理弹射、RPG升级和策略选择元素,通过简单的操作提供深度游戏体验。玩家需要不断优化发射策略并选择适合的升级路线来挑战更高分数。

相关推荐
YuTaoShao几秒前
Java八股文——计算机网络「网络攻击篇」
java·开发语言·计算机网络
bubiyoushang8889 分钟前
Kotlin中快速实现MVI架构
android·开发语言·kotlin
DBWYX2 小时前
PHP is the best language.
开发语言·php
何朴尧2 小时前
全局数据的处理
开发语言
Web极客码2 小时前
如何在中将网络改为桥接模式并配置固定IP地址
开发语言·网络·ubuntu·php·虚拟机
T风呤3 小时前
QT历史版本,5.15.2使用清华源半小时安装速成
开发语言·qt
晨曦5432103 小时前
针对经济学大数据的 Python 爬虫实践指南
开发语言·爬虫·python
上位机付工3 小时前
C#上位机实现报警语音播报
开发语言·c#·上位机·plc·运动控制卡·语音播报·报警播报
千千道3 小时前
QT 中使用 QSettings 读写 ini 配置文件
开发语言·qt
benben0444 小时前
Unity3D仿星露谷物语开发67之创建新的NPC
开发语言·游戏·ui·c#·游戏引擎