用Go写一个《植物大战僵尸》小游戏:支持鼠标放僵尸、胜利失败判定!

你有没有想过,用 Go语言 也能写小游戏?今天就带大家用不到 200 行代码,打造一个简版《植物大战僵尸》!

不仅能 自动射击判断胜负 ,还可以 用鼠标点击放僵尸挑战自己,实现真正的人机对抗!


游戏玩法

  • 植物固定位置自动发射子弹
  • 点击鼠标左键放置僵尸,向左移动
  • 子弹打中僵尸可造成伤害,击败 10 个获胜!
  • 有僵尸闯进防线则游戏失败

技术点

  • • 游戏开发框架:Ebiten
  • • 植物发射逻辑:定时自动生成子弹
  • • 僵尸行为:匀速向左移动,碰到子弹扣血
  • • 鼠标点击:在任意位置生成僵尸
  • • 游戏结局:胜利 or 失败提示

完整代码(Go + Ebiten)

go 复制代码
package main

import (
    "fmt"
    "image/color"
    "log"
    "math"
    "math/rand"
    "time"

    "github.com/hajimehoshi/ebiten/v2"
    "github.com/hajimehoshi/ebiten/v2/ebitenutil"
)

type Zombie struct {
    x, y float64
    hp   int
}

type Bullet struct {
    x, y float64
}

type Game struct {
    zombies       []Zombie
    bullets       []Bullet
    shootCD       int
    mouseDown     bool
    zombiesKilled int
    gameOver      bool
    gameWin       bool
}

func (g *Game) Update() error {
    if g.gameOver {
        return nil
    }

    // 自动发射子弹
    if g.shootCD <= 0 {
        g.bullets = append(g.bullets, Bullet{x: 100, y: 200})
        g.shootCD = 15
    } else {
        g.shootCD--
    }

    // 更新子弹
    newBullets := []Bullet{}
    for _, b := range g.bullets {
        b.x += 6
        if b.x < 800 {
            newBullets = append(newBullets, b)
        }
    }
    g.bullets = newBullets

    // 更新僵尸
    newZombies := []Zombie{}
    for _, z := range g.zombies {
        z.x -= 1.2
        if z.x <= 0 {
            g.gameOver = true
            g.gameWin = false
            return nil
        }

        hit := false
        for i := range g.bullets {
            if math.Abs(z.x-g.bullets[i].x) < 10 && math.Abs(z.y-g.bullets[i].y) < 10 {
                z.hp--
                if z.hp <= 0 {
                    hit = true
                    g.zombiesKilled++
                    if g.zombiesKilled >= 10 {
                        g.gameOver = true
                        g.gameWin = true
                        return nil
                    }
                    break
                }
            }
        }
        if !hit {
            newZombies = append(newZombies, z)
        }
    }
    g.zombies = newZombies

    // 鼠标左键放僵尸
    if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
        if !g.mouseDown {
            x, y := ebiten.CursorPosition()
            g.zombies = append(g.zombies, Zombie{
                x:  float64(x),
                y:  float64(y),
                hp: 3,
            })
            g.mouseDown = true
        }
    } else {
        g.mouseDown = false
    }

    return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
    screen.Fill(color.RGBA{0xCC, 0xFF, 0xCC, 0xFF})

    // 植物
    ebitenutil.DrawRect(screen, 100, 200, 20, 20, color.RGBA{0x00, 0x88, 0x00, 0xFF})

    // 子弹
    for _, b := range g.bullets {
        ebitenutil.DrawRect(screen, b.x, b.y, 5, 5, color.RGBA{0x00, 0x00, 0xFF, 0xFF})
    }

    // 僵尸
    for _, z := range g.zombies {
        ebitenutil.DrawRect(screen, z.x, z.y, 20, 20, color.RGBA{0x88, 0x00, 0x00, 0xFF})
    }

    // 文本信息
    msg := "点击鼠标左键放置僵尸! 已击败僵尸:" + itoa(g.zombiesKilled)
    if g.gameOver {
        if g.gameWin {
            msg = " 胜利!你击败了10个僵尸!"
        } else {
            msg = " 游戏失败!有僵尸入侵了!"
        }
    }
    ebitenutil.DebugPrint(screen, msg)
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return 800, 600
}

func itoa(n int) string {
    return fmt.Sprintf("%d", n)
}

func main() {
    rand.Seed(time.Now().UnixNano())
    game := &Game{}
    ebiten.SetWindowSize(800, 600)
    ebiten.SetWindowTitle("Go版植物大战僵尸 - 加入胜利/失败判定")
    if err := ebiten.RunGame(game); err != nil {
        log.Fatal(err)
    }
}

编译运行方法

    1. 安装依赖(需要 Go 和 Ebiten):
arduino 复制代码
go get github.com/hajimehoshi/ebiten/v2
    1. 运行程序:
go 复制代码
go run main.go

最后

这个小游戏只是开始,后续你可以扩展:

  • • 不同种类植物与僵尸
  • • 子弹特效
  • • 多行战斗区域
  • • 商店系统与阳光资源管理

如果你对游戏开发有兴趣,Go + Ebiten 是一个极具潜力的组合!

相关推荐
审计侠3 分钟前
Go语言-初学者日记(八):构建、部署与 Docker 化
开发语言·后端·golang
AskHarries15 分钟前
如何开通google Free Tier长期免费云服务器(1C/1G)
后端
码界筑梦坊18 分钟前
基于Django的二手交易校园购物系统
大数据·后端·python·信息可视化·django
东方珵蕴20 分钟前
Logo语言的区块链
开发语言·后端·golang
烛阴21 分钟前
从零到RESTful API:Express路由设计速成手册
javascript·后端·express
uhakadotcom28 分钟前
Mars与PyODPS DataFrame:功能、区别和使用场景
后端·面试·github
信徒_1 小时前
Spring 怎么解决循环依赖问题?
java·后端·spring
小杨4042 小时前
springboot框架项目实践应用十五(扩展sentinel区分来源)
spring boot·后端·spring cloud
二狗哈2 小时前
go游戏后端开发24:写完赢三张游戏
python·游戏·golang
FirstMrRight2 小时前
自动挡线程池OOM最佳实践
java·后端