当前位置: 首页 > article >正文

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)
	}
}

游戏特色说明:

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

操作方法:

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

扩展建议:

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

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


http://www.kler.cn/a/544608.html

相关文章:

  • 伯克利 CS61A 课堂笔记 08 —— Strings and Dictionaries
  • 解析 JavaScript 面试题:`index | 0` 确保数组索引为整数
  • 数据库安全、分布式数据库、反规范化等新技术(高软19)
  • 连锁收银系统的核心架构与技术选型
  • 51c自动驾驶~合集50
  • Tweak Power:高效电脑系统优化利器
  • ubuntu 实时系统安装Nvidia驱动
  • 小米红米手机澎湃2.0解锁BL 绕澎湃社区验证 救砖以及9008授权
  • 优雅的git log输出内容更加醒目
  • 【愚公系列】《Python网络爬虫从入门到精通》007-请求模块requests高级应用(Reguests-HTML)
  • Kubernetes部署OwnCloud网盘服务
  • 基于javaweb的SpringBoot+MyBatis健身房信息管理系统(源码+文档+部署讲解)
  • 深入理解DeepSeek与企业实践(二):32B多卡推理的原理、硬件散热与性能实测
  • 06:串口通信
  • python使用虚拟环境
  • Python 依赖管理的革新——Poetry 深度解析
  • C# Dictionary的实现原理
  • 走进 Tcl 语言:历史、特性与应用
  • 数据结构:图论入门
  • JavaSE基本知识补充 -IO流